的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类是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类也是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;
}
除了类名和图像文件的路径之外,两种实现都是相同的。两个文件(test.png(绿色图像)和player.png(蓝色图像))都存在并且可以成功加载。当我运行程序时,player.png呈现在 SplashScreen类。 但是当我将游戏类中的屏幕从SplashScreen更改为MenuScreen时,将调用所有MenuScreen函数,但不会渲染纹理。 SDL_GetError()不会返回任何错误,我没有得到任何异常,纹理和渲染器不为空(已经检查),我在屏幕上看不到任何东西(它是黑屏)。 如果一切正常,你应该在屏幕上看到一个彩色方块。
更新
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;
};
答案 0 :(得分:0)
您的代码从不调用MenuScreen::create
方法,因此永远不会创建SDL_Texture
。
您在评论中说您检查了属性tex
的值并且它不为空,但由于它未在构造函数中初始化,因此它可能包含随机值
这些是与您的问题直接相关的更一般的评论,但正如我在评论中所说,您应该真正改变您的程序架构,因为您有很多固有的错误来自它。例如,当您将屏幕指针切换到MenuScreen的指针时,您会泄漏SplashScreen对象。
你应该看看C ++中的一个好的游戏状态引擎,并将启动屏幕,菜单和任何其他游戏状态作为状态引擎中的状态进行管理。例如,this tutorial具有良好的基本状态机实现。