SDL_Texture 没有在第二个实例中绘制

SDL_Texture doesn't get drawn in second instance

main.cpp

#include "SDL.h"
#include <cstdio>
#include <iostream>
#include "Game.h"

//Constants
bool isFullscreen = false;
const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;
const char *GAME_NAME = "Alex's RPG Game | Version 2";

//Game
Game *game = nullptr; //Game is null --> nullpointer


int main(int argc, char* argv[]) {
    //Ignore the arguments

    std::cout << "Starting game" << std::endl;

    game = new Game();

    game->init(GAME_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_RESIZABLE);

    while (game->isGameRunning()){
        game->handleEvents();
        game->update();
        game->render();
    }

    game->destroy();

    return 0;
}

game.cpp:

Game::Game() {
    isRunning = false;
    screen = new SplashScreen(getGame());
}

Game::~Game() {
    //Empty deconstructor
}

void Game::init(const char *title, int xPos, int yPos, int width, int height, Uint32 flag) {

    if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {

        std::cout << "Subsystems are running..." << std::endl;

        window = SDL_CreateWindow(title, xPos, yPos, width, height, flag);

        if (window) {
            std::cout << "Window created" << std::endl;
        }

        renderer = SDL_CreateRenderer(window, -1, 0);


        if (renderer) {
            //Draw a black background
            SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
            std::cout << "Renderer created" << std::endl;
        }

        screen->create(renderer);

        std::cout << "Game successful initiated" << std::endl;
        isRunning = true;


    } else {
        isRunning = false;
    }

}

void Game::render() {

    SDL_RenderClear(renderer);

    screen->render(renderer);

    SDL_RenderPresent(renderer);
}

void Game::destroy() {
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    SDL_Quit();
    std::cout << "Game successful destroyed" << std::endl;
}

void Game::update() {
    screen->update();
}

void Game::handleEvents() {

    SDL_PollEvent(&event);
    switch (event.type) {
        case SDL_QUIT:
            isRunning = false;
            break;
        case SDL_KEYDOWN:
            switch (event.key.keysym.sym){
                case SDLK_ESCAPE:
                    isRunning = false;
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }

}

bool Game::isGameRunning() {
    return isRunning;
}

void Game::setScreen(IScreen *screen1) {
    screen = screen1;
}

game.h

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

    void init(const char* title, int xPos, int yPos, int width, int height, Uint32 flag);

    void handleEvents();
    void update();
    void render();
    void setScreen(IScreen *screen1);
    void destroy();

    Game* getGame(){
        return this;
    }

    bool isGameRunning();

private:
    bool isRunning;

    //Define a pointer to a window and a renderer
    SDL_Window *window;
    SDL_Renderer *renderer;
    SDL_Event event;

    IScreen *screen;

};

SplashScreen.h

class SplashScreen: public IScreen{
public:

    explicit SplashScreen(Game *game);
    ~SplashScreen();

    void render(SDL_Renderer *renderer) override;
    void update() override;
    void create(SDL_Renderer *renderer) override;

private:
    SDL_Texture *texture;
    SDL_Rect rect;

    Game *game;

    int time = 0;

};

SplashScreen.cpp class 是 IScreen

的一个实现
SplashScreen::SplashScreen(Game *game1){

    //Constructor
    game = game1;
}

SplashScreen::~SplashScreen(){

    //Deconstructor

}

void SplashScreen::update() {
    // Update the screen

    if(SDL_GetTicks() > 5000 + time){
        game->setScreen(new MenuScreen(game));
    }

}

void SplashScreen::render(SDL_Renderer *renderer) {

    SDL_RenderCopy(renderer, texture, NULL, &rect);

}


void SplashScreen::create(SDL_Renderer *renderer) {

    texture = TextureManager::loadTexture("player.png", renderer);

    rect.x = 50;
    rect.y = 50;
    rect.h = 32;
    rect.w = 32;

    time = SDL_GetTicks();

}

MenuScreen.h

class MenuScreen: public IScreen{
public:

    explicit MenuScreen(Game *game1);
    ~MenuScreen();

    void render(SDL_Renderer *renderer) override;
    void update() override;
    void create(SDL_Renderer *renderer) override;

private:
    SDL_Texture *tex;
    SDL_Rect rect;

    Game *game;

};

MenuScreen.cpp class 也是 IScreen 的一个实现:

MenuScreen::MenuScreen(Game *game1) {
    game = game1;
}

MenuScreen::~MenuScreen() {

}

void MenuScreen::update() {
    std::cout << "Why can't it render" << std::endl;
}

void MenuScreen::render(SDL_Renderer *renderer) {

    std::cout << "Why can't it render" << std::endl;

    SDL_RenderCopy(renderer, tex, nullptr, &rect);

}

void MenuScreen::create(SDL_Renderer *renderer) {

    tex = TextureManager::loadTexture("test.png", renderer);

    rect.x = 100;
    rect.y = 100;
    rect.h = 32;
    rect.w = 32;

}

除了它们的 class 名称和图像文件的路径之外,这两种实现是相同的。这两个文件(test.png(绿色图像)和 player.png(蓝色图像))都存在并且可以成功加载。当我 运行 程序时, player.png 呈现在 启动画面 class。 但是,当我将游戏 class 中的屏幕从 SplashScreen 更改为 MenuScreen 时,会调用所有 MenuScreen 函数,但不会渲染纹理。 SDL_GetError() 没有 return 任何错误,我没有得到任何异常,纹理和渲染器不为空(已经检查)并且我在屏幕上看不到任何东西(它是黑屏)。 如果一切正常,您应该会在屏幕上看到一个彩色方块。

更新:

TextureManager.cpp

SDL_Texture *TextureManager::loadTexture(const char *path, SDL_Renderer *renderer) {

    SDL_Surface* surface = IMG_Load(path);
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_FreeSurface(surface);
    return texture;
}

IScreen.h

#include "SDL.h"

class IScreen{
public:

    virtual void create(SDL_Renderer *renderer) = 0;

    virtual void render(SDL_Renderer *renderer) = 0;
    virtual void update() = 0;


};

您的代码从不调用 MenuScreen::create 方法,因此您的 SDL_Texture 永远不会创建。

你在评论中说你检查了属性 tex 的值并且它不是空的,但由于它没有在构造函数中初始化,它可能包含一个随机值。


这些是比与您的问题直接相关的更笼统的评论,但就像我在评论中所说的那样,您确实应该更改您的程序架构,因为它有很多固有的错误。例如,当您将屏幕指针切换到 MenuScreen 的指针时,您会泄漏 SplashScreen 对象。

你应该看看一个很好的 C++ 游戏状态引擎,并将启动画面、菜单和任何其他游戏状态作为状态引擎中的状态进行管理。例如,this tutorial 有一个很好的基本状态机实现。