SDL 2.0 C ++:Polymorphism Vectors,我的对象没有加载不同的图像

时间:2014-08-16 21:14:45

标签: c++ sdl sdl-2

所以我基本上按照Shaun Mitchell的一本名为SDL游戏开发的书。 我是第58页的最新信息,它告诉我们如何实现多态性。

到目前为止,我所拥有的是: - 创建我们进行所有渲染更新等的主代码(Game.cpp和Game.h)
- 创建纹理管理器作为单例(TextureManager.h和TextureManager.cpp)
- 创建GameObject(GameObject.h和GameObject.cpp)
- 创建一个继承GameObject(Player.h和Player.cpp)的播放器

所以我的GameObject类基本上有3种方法:加载,绘制和更新。 加载基本上加载图像,我使用我的TextureManager来执行此操作。 绘制它并更新只是改变它的位置和当前帧。

我传递了图像的名称,它基本上是我称之为Game类的目录,渲染器和textureID。

基本上问题是我将两个不同的目录传递给GameObject 和一个播放器,但它只加载我传入的最后一个目录。因为GameObject和Player都变成了同一个图像。

所以我认为问题在于Game类,Player类或GameObject类。 我在Game类中创建了对象,并在init.c函数中将它们传递到了Game.cpp中 在哪里说

    m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate",m_pRenderer);    
    m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate",m_pRenderer);   

GameObject.h

#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H

#include <string>
#include <iostream>
#include "SDL_image.h"
#include "TextureManager.h"

class GameObject
{
    public:
        virtual bool load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer);
        virtual void draw(SDL_Renderer* pRenderer);
        virtual void update();
        virtual void clean();
    protected:
        std::string m_textureID;
        int m_currentFrame;
        int m_currentRow;
        int m_x;
        int m_y;
        int m_width;
        int m_height;
};

#endif // GAMEOBJECT_H

GameObject.cpp

#include "GameObject.h"

bool GameObject::load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer)
{
    m_x = x;
    m_y = y;
    m_width = width;
    m_height = height;
    m_textureID = textureID;
    m_currentRow = 1;
    m_currentFrame = 1;
    if(!TextureManager::Instance()->load(name, textureID, pRenderer))
    {
        return false;
    }
    return true;
}

void GameObject::draw(SDL_Renderer* pRenderer)
{
    TextureManager::Instance()->drawFrame(m_textureID, m_x, m_y,m_width, m_height, m_currentRow, m_currentFrame, pRenderer);
}

void GameObject::update()
{
    m_x += 1;
    m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
}

void GameObject::clean()
{

}

在我的Player类中,我做同样的事情,除了我使用已经在GameObject中创建的方法

Player.h

#ifndef PLAYER_H
#define PLAYER_H

#include "GameObject.h"
class Player : public GameObject
{
    public:
        bool load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer);
        void draw(SDL_Renderer* pRenderer);
        void update();
        void clean();
};

#endif // PLAYER_H

Player.cpp

#include "Player.h"

bool Player::load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer)
{
    if(!GameObject::load(x, y, width, height, name, textureID, pRenderer))
    {
        return false;
    }
    return true;
}

void Player::draw(SDL_Renderer* pRenderer)
{
    GameObject::draw(pRenderer);
}


void Player::update()
{
    m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
    m_x -= 1;
}


void Player::clean()
{

}

这是图像不会在Game.cpp中加载相同内容的部分 所以我基本上创建了一个包含GameObjects的向量,它告诉我使用它,以便每当我想绘制对象时我只能循环遍历它

Game.h

#ifndef GAME_H
#define GAME_H

#include <SDL.h>
#include <SDL_image.h>
#include <string.h>
#include <iostream>
#include <vector>
#include "TextureManager.h"
#include "Player.h"


class Game
{
    public:
        Game() {}
        ~Game() {}

        bool init(const char* title, int xpos, int ypos, int width, int height, int flags);
        void render();
        void update();
        void handleEvents();
        void clean();


        // a function to access the private running variable
        bool running() { return m_bRunning; }

    private:
        SDL_Window* m_pWindow;
        SDL_Renderer* m_pRenderer;
        int m_currentFrame;
        bool m_bRunning;
        GameObject* m_go;
        GameObject* m_player;
        std::vector<GameObject*> m_gameObjects;


};

#endif

Game.cpp

#include "Game.h"


typedef TextureManager TheTextureManager; // Singleton TextureManager
Game* g_game = 0; // Game Object

bool Game::init(const char* title, int xpos, int ypos, int width,int height, int flags)
{
    // attempt to initialize SDL



    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos,width, height, flags);
        if(m_pWindow != 0) // window init success
    {
    std::cout << "window creation success\n";
    m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
    if(m_pRenderer != 0) // renderer init success
    {
        std::cout << "renderer creation success\n";
        SDL_SetRenderDrawColor(m_pRenderer,255,255,255,255);
    }
    else
    {
        std::cout << "renderer init fail\n";
        return false; // renderer init fail
    }
    }
    else
    {
        std::cout << "window init fail\n";
        return false; // window init fail
    }
    }
    else
    {
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
    }
    std::cout << "init success\n";

    m_go = new GameObject();
    m_player = new Player();
    m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate",m_pRenderer);
    m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate",m_pRenderer);
    m_gameObjects.push_back(m_go);
    m_gameObjects.push_back(m_player);


    m_bRunning = true; // everything inited successfully, start the main loop
    return true;

}

void Game::render()
{
    SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color

    //m_go.draw(m_pRenderer);
    //m_player.draw(m_pRenderer);
    for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); i++)
    {
        m_gameObjects[i]->draw(m_pRenderer);
    }

    SDL_RenderPresent(m_pRenderer); // draw to the screen
}

void Game::clean()
{
    std::cout << "cleaning game\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}

void Game::handleEvents()
{
    SDL_Event event;
    if(SDL_PollEvent(&event))
    {
        switch (event.type)
        {
        case SDL_QUIT:
            m_bRunning = false;
            break;
            default:
            break;
        }
    }
}
void Game::update()
{
    //m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
    //m_go.update();
    //m_player.update();
    for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); i++)
    {
        m_gameObjects[i]->update();
    }
}

int main(int argc, char* argv[])
{
    g_game = new Game();
    g_game->init("Chapter 1", 100, 100, 640, 480, 0);
    while(g_game->running())
    {
        g_game->render();
        g_game->handleEvents();
        g_game->update();
        SDL_Delay(10); // add the delay
    }
    g_game->clean();
    return 0;
}

正如你在init函数结束时看到的那样,我有m_go加载simba,m_player加载下载。即使它们向不同的方向移动(GameObject向右移动,播放器向左移动,如更新方法中的类所示)。

我的程序只为两者加载下载。

我不确定TextureManager类是否相关,但我还是会发布它 TextureManager.h

#ifndef TEXTUREMANAGER_H
#define TEXTUREMANAGER_H


#include <SDL.h>
#include <SDL_image.h>
#include <string.h>
#include <iostream>
#include <map>
class TextureManager
{
    public:
        bool load(std::string fileName,std::string id,SDL_Renderer* pRenderer);
        void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
        void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
        std::map <std::string, SDL_Texture*> m_textureMap;

        static TextureManager* Instance()
        {
            if(s_pInstance == 0)
            {
                s_pInstance = new TextureManager();
                return s_pInstance;
            }
        return s_pInstance;
        }
        //typedef TextureManager TheTextureManager;
    protected:
    private:
        TextureManager(){}
        static TextureManager* s_pInstance;

};

#endif // TEXTUREMANAGER_H

TextureManager.cpp

#include "TextureManager.h"

TextureManager* TextureManager::s_pInstance = 0;

bool TextureManager::load(std::string fileName, std::string id, SDL_Renderer* pRenderer)
{
    SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());
    if(pTempSurface == 0)
    {
        return false;
    }
    SDL_Texture* pTexture =
    SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);
    // everything went ok, add the texture to our list
    if(pTexture != 0)
    {
        m_textureMap[id] = pTexture;
        return true;
    }
// reaching here means something went wrong
    return false;
}

void TextureManager::draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip)
{
    SDL_Rect srcRect;
    SDL_Rect destRect;

    srcRect.x = 0;
    srcRect.y = 0;
    srcRect.w = destRect.w = width;
    srcRect.h = destRect.h = height;
    destRect.x = x;
    destRect.y = y;
    SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect,
    &destRect, 0, 0, flip);
}

void TextureManager::drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer *pRenderer, SDL_RendererFlip flip)
{
    SDL_Rect srcRect;
    SDL_Rect destRect;
    srcRect.x = width * currentFrame;
    srcRect.y = height * (currentRow - 1);
    srcRect.w = destRect.w = width;
    srcRect.h = destRect.h = height;
    destRect.x = x;
    destRect.y = y;
    SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect,
    &destRect, 0, 0, flip);
}

1 个答案:

答案 0 :(得分:0)

您正在使用&#34; animate&#34; textureID不止一次 - 这需要是唯一的

您的密码:

m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate", m_pRenderer);    
m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate", m_pRenderer)

纹理被加载会发生什么,但它会覆盖现有的纹理,该纹理具有&#34; animate&#34;键入地图。使它们独一无二,这应该可以解决您的问题。