SDL 渲染不工作
SDL render not working
我在游戏中创建第二个 class 时遇到问题,这是玩家 class 但是当我调用 texturemanager 绘制游戏时,它不起作用,但是当我直接调用 texturemanager 来绘制它正在工作的播放器。这是我的 class.
Game.h
#pragma once
#include <SDL/SDL.h>
#include "TextureManager.h"
#include "Player.h"
class Game
{
public:
Game(void);
~Game(void);
void startGame();
void init();
void gameLoop();
void eventHandler();
void render();
void exitGame();
private:
bool _isRunning;
SDL_Window* _window;
SDL_Renderer* _renderer;
SDL_Rect _spriteClips[2];
TextureManager _textureManager;
Player _player;
};
Game.cpp
#include "Game.h"
#include "Error.h"
Game::Game(void)
{
_window = nullptr;
_isRunning = true;
}
Game::~Game(void)
{
}
void Game::startGame()
{
init();
gameLoop();
}
void Game::init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
_window = SDL_CreateWindow("Renderer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480, SDL_WINDOW_SHOWN);
if (_window != nullptr)
{
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(_renderer!= nullptr)
{
SDL_SetRenderDrawColor(_renderer, 255, 255, 255, 255);
}
else
fatalError("Failed to create renderer");
}
else
fatalError("Failed to create window!");
}
else
fatalError("Failed to initialize SDL!");
// temp image load
_textureManager.loadFromFile("assets/tiles.png", _renderer);
_spriteClips[0].x = 0;
_spriteClips[0].y = 160;
_spriteClips[0].w = 80;
_spriteClips[0].h = 80;
_spriteClips[1].x = 0;
_spriteClips[1].y = 80;
_spriteClips[1].w = 80;
_spriteClips[1].h = 80;
}
void Game::gameLoop()
{
while (_isRunning != false)
{
eventHandler();
render();
}
exitGame();
}
void Game::eventHandler()
{
SDL_Event evnt;
while (SDL_PollEvent(&evnt))
{
switch (evnt.type)
{
case SDL_QUIT:
_isRunning = false;
break;
}
}
}
void Game::render()
{
SDL_RenderClear(_renderer);
_textureManager.draw(0, 0, &_spriteClips[0], _renderer);
_player.draw(200, 200, &_spriteClips[1], _renderer);
// when i used this, it is working
//_textureManager.draw(200, 200, &_spriteClips[1], _renderer);
SDL_RenderPresent(_renderer);
}
void Game::exitGame()
{
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
_window = nullptr;
_renderer = nullptr;
SDL_Quit();
}
TextureManager.h
#pragma once
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <string>
class TextureManager
{
public:
TextureManager(void);
~TextureManager(void);
bool loadFromFile(std::string filePath, SDL_Renderer* renderer);
void free();
void draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer);
int getWidth() { return _width; }
int getHeight() { return _height; }
private:
SDL_Texture* _texture;
int _width;
int _height;
};
TextureManager.cpp
#include "TextureManager.h"
#include "Error.h"
TextureManager::TextureManager(void)
{
_texture = nullptr;
_width = 0;
_height = 0;
}
TextureManager::~TextureManager(void)
{
free();
}
bool TextureManager::loadFromFile(std::string filePath , SDL_Renderer* renderer)
{
free();
SDL_Texture* newTexture = nullptr;
SDL_Surface* loadedSurface = IMG_Load(filePath.c_str());
if(loadedSurface != nullptr)
{
SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF));
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if(newTexture != nullptr)
{
_width = loadedSurface->w;
_height = loadedSurface->h;
}
else
fatalError("unable to create texture from surface!");
SDL_FreeSurface(loadedSurface);
}
else
fatalError("unable to load image path " + filePath);
_texture = newTexture;
return _texture != nullptr;
}
void TextureManager::draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer)
{
SDL_Rect renderQuad = { x, y, _width, _height };
if (clip != nullptr)
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
SDL_RenderCopy(renderer, _texture, clip, &renderQuad);
}
void TextureManager::free()
{
if (_texture != nullptr)
{
SDL_DestroyTexture(_texture);
_texture = nullptr;
_width = 0;
_height = 0;
}
}
Player.h
#pragma once
#include "TextureManager.h"
class Player
{
public:
Player(void);
~Player(void);
void draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer);
private:
TextureManager _textureManager;
};
Player.cpp
#include "Player.h"
Player::Player(void)
{
}
Player::~Player(void)
{
}
void Player::draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer)
{
_textureManager.draw(x, y, clip, renderer);
}
那是因为 Game
和 Player
有两个不同的纹理管理器。游戏会初始化其纹理管理器,这就是为什么当您直接使用它时它会起作用的原因。 Player
从不初始化它的管理器,这就是为什么当你使用它时没有绘制任何东西。
要修复它,您可能希望只有一个纹理管理器,即 Game
class 中的那个,并且 Player
只存储一个指针或引用给它。这是修复它的一种方法:
将Player
class中_textureManager
的类型改为Game
class中的_textureManager
作为参考:
TextureManager& _textureManager;
让 Player class 在其构造函数中接受 TextureManager 引用,并使用它来初始化私有成员:
Player::Player(TextureManager& textureManager)
: _textureManager(textureManager)
{
}
使 Game 对象在其构造函数中正确初始化玩家:
Game::Game(void)
: _player(_textureManager)
{
...
通过这些更改,您的代码现在应该可以工作了。
我在游戏中创建第二个 class 时遇到问题,这是玩家 class 但是当我调用 texturemanager 绘制游戏时,它不起作用,但是当我直接调用 texturemanager 来绘制它正在工作的播放器。这是我的 class.
Game.h
#pragma once
#include <SDL/SDL.h>
#include "TextureManager.h"
#include "Player.h"
class Game
{
public:
Game(void);
~Game(void);
void startGame();
void init();
void gameLoop();
void eventHandler();
void render();
void exitGame();
private:
bool _isRunning;
SDL_Window* _window;
SDL_Renderer* _renderer;
SDL_Rect _spriteClips[2];
TextureManager _textureManager;
Player _player;
};
Game.cpp
#include "Game.h"
#include "Error.h"
Game::Game(void)
{
_window = nullptr;
_isRunning = true;
}
Game::~Game(void)
{
}
void Game::startGame()
{
init();
gameLoop();
}
void Game::init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
_window = SDL_CreateWindow("Renderer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480, SDL_WINDOW_SHOWN);
if (_window != nullptr)
{
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(_renderer!= nullptr)
{
SDL_SetRenderDrawColor(_renderer, 255, 255, 255, 255);
}
else
fatalError("Failed to create renderer");
}
else
fatalError("Failed to create window!");
}
else
fatalError("Failed to initialize SDL!");
// temp image load
_textureManager.loadFromFile("assets/tiles.png", _renderer);
_spriteClips[0].x = 0;
_spriteClips[0].y = 160;
_spriteClips[0].w = 80;
_spriteClips[0].h = 80;
_spriteClips[1].x = 0;
_spriteClips[1].y = 80;
_spriteClips[1].w = 80;
_spriteClips[1].h = 80;
}
void Game::gameLoop()
{
while (_isRunning != false)
{
eventHandler();
render();
}
exitGame();
}
void Game::eventHandler()
{
SDL_Event evnt;
while (SDL_PollEvent(&evnt))
{
switch (evnt.type)
{
case SDL_QUIT:
_isRunning = false;
break;
}
}
}
void Game::render()
{
SDL_RenderClear(_renderer);
_textureManager.draw(0, 0, &_spriteClips[0], _renderer);
_player.draw(200, 200, &_spriteClips[1], _renderer);
// when i used this, it is working
//_textureManager.draw(200, 200, &_spriteClips[1], _renderer);
SDL_RenderPresent(_renderer);
}
void Game::exitGame()
{
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
_window = nullptr;
_renderer = nullptr;
SDL_Quit();
}
TextureManager.h
#pragma once
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <string>
class TextureManager
{
public:
TextureManager(void);
~TextureManager(void);
bool loadFromFile(std::string filePath, SDL_Renderer* renderer);
void free();
void draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer);
int getWidth() { return _width; }
int getHeight() { return _height; }
private:
SDL_Texture* _texture;
int _width;
int _height;
};
TextureManager.cpp
#include "TextureManager.h"
#include "Error.h"
TextureManager::TextureManager(void)
{
_texture = nullptr;
_width = 0;
_height = 0;
}
TextureManager::~TextureManager(void)
{
free();
}
bool TextureManager::loadFromFile(std::string filePath , SDL_Renderer* renderer)
{
free();
SDL_Texture* newTexture = nullptr;
SDL_Surface* loadedSurface = IMG_Load(filePath.c_str());
if(loadedSurface != nullptr)
{
SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF));
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if(newTexture != nullptr)
{
_width = loadedSurface->w;
_height = loadedSurface->h;
}
else
fatalError("unable to create texture from surface!");
SDL_FreeSurface(loadedSurface);
}
else
fatalError("unable to load image path " + filePath);
_texture = newTexture;
return _texture != nullptr;
}
void TextureManager::draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer)
{
SDL_Rect renderQuad = { x, y, _width, _height };
if (clip != nullptr)
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
SDL_RenderCopy(renderer, _texture, clip, &renderQuad);
}
void TextureManager::free()
{
if (_texture != nullptr)
{
SDL_DestroyTexture(_texture);
_texture = nullptr;
_width = 0;
_height = 0;
}
}
Player.h
#pragma once
#include "TextureManager.h"
class Player
{
public:
Player(void);
~Player(void);
void draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer);
private:
TextureManager _textureManager;
};
Player.cpp
#include "Player.h"
Player::Player(void)
{
}
Player::~Player(void)
{
}
void Player::draw(int x, int y, SDL_Rect* clip, SDL_Renderer* renderer)
{
_textureManager.draw(x, y, clip, renderer);
}
那是因为 Game
和 Player
有两个不同的纹理管理器。游戏会初始化其纹理管理器,这就是为什么当您直接使用它时它会起作用的原因。 Player
从不初始化它的管理器,这就是为什么当你使用它时没有绘制任何东西。
要修复它,您可能希望只有一个纹理管理器,即 Game
class 中的那个,并且 Player
只存储一个指针或引用给它。这是修复它的一种方法:
将Player
class中_textureManager
的类型改为Game
class中的_textureManager
作为参考:
TextureManager& _textureManager;
让 Player class 在其构造函数中接受 TextureManager 引用,并使用它来初始化私有成员:
Player::Player(TextureManager& textureManager)
: _textureManager(textureManager)
{
}
使 Game 对象在其构造函数中正确初始化玩家:
Game::Game(void)
: _player(_textureManager)
{
...
通过这些更改,您的代码现在应该可以工作了。