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);
}

那是因为 GamePlayer 有两个不同的纹理管理器。游戏会初始化其纹理管理器,这就是为什么当您直接使用它时它会起作用的原因。 Player 从不初始化它的管理器,这就是为什么当你使用它时没有绘制任何东西。

要修复它,您可能希望只有一个纹理管理器,即 Game class 中的那个,并且 Player 只存储一个指针或引用给它。这是修复它的一种方法:

Playerclass中_textureManager的类型改为Gameclass中的_textureManager作为参考:

TextureManager& _textureManager;

让 Player class 在其构造函数中接受 TextureManager 引用,并使用它来初始化私有成员:

Player::Player(TextureManager& textureManager)
          : _textureManager(textureManager)
{
}

使 Game 对象在其构造函数中正确初始化玩家:

Game::Game(void)
        : _player(_textureManager)
{
    ...

通过这些更改,您的代码现在应该可以工作了。