SDL2 无法从矢量渲染实体

SDL2 cannot render entities from vector

我使用 SDL2 已经有一段时间了。渲染单个纹理完全没有问题,尽管在我将这些纹理包裹在一个实体 class 中并将它们放入一个向量中之后,事情就不再起作用了(呈现黑屏)。有人知道为什么吗?

main.cpp

#include "RenderWindow.hpp"
#include "vec.h"
#include "entity.h"

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include <iostream>
#include <vector>

int main(int argc, char* argv[]) {
    if (SDL_Init(SDL_INIT_VIDEO) > 0) {
        std::cout << "Could not Init VIDEO, Error: " << SDL_GetError() << std::endl;
        return 0;
    }

    if (!IMG_Init(IMG_INIT_PNG)) {
        std::cout << "Could not Init IMG, Error: " << SDL_GetError() << std::endl;
        return 0;
    }

    RenderWindow r("Bread.", 600, 600);

    // entity vector
    std::vector<Entity> entities = {Entity(Vec2i{5, 5}, r.CreateTexture("res/gfx/bob.png"))};

    // single entity
    Entity bob(Vec2i{5, 5}, r.CreateTexture("res/gfx/bob.png"));

    bool running = true;
    SDL_Event event;
    while (running) {
        Uint64 start = SDL_GetPerformanceCounter();

        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                running = false;
            }
        }

        r.Clear();

        // doesn't render (black screen)
        for (const Entity& e : entities) {
            r.RenderEntity(e);
        }

        // renders fine
        r.RenderEntity(bob);

        r.Display();

        Uint64 end = SDL_GetPerformanceCounter();
        float elapsedMS = (end - start) / (float)SDL_GetPerformanceFrequency() * 1000.0f;
        SDL_Delay(floor(16.666f - elapsedMS));
    }
    return 0;
}

RenderWindow.cpp

#include "RenderWindow.hpp"

#include <iostream>


RenderWindow::RenderWindow(const char* p_title, int32_t p_w, int32_t p_h)
    : window(NULL), renderer(NULL) {
    this->window = SDL_CreateWindow(p_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, p_w, p_h, SDL_WINDOW_SHOWN);
    if (this->window == NULL) {
        std::cout << "Failed to initialize window, Error: " << SDL_GetError() << std::endl;
    }

    this->renderer = SDL_CreateRenderer(this->window, -1, SDL_RENDERER_ACCELERATED);
    if (this->renderer == NULL) {
        std::cout << "Failed to initialize renderer, Error: " << SDL_GetError() << std::endl;
    }
}

RenderWindow::~RenderWindow() {
    SDL_DestroyWindow(this->window);
    SDL_DestroyRenderer(this->renderer);
    SDL_Quit();
}

SDL_Texture* RenderWindow::CreateTexture(const char* p_path) {
    return IMG_LoadTexture(this->renderer, p_path);
}

void RenderWindow::Clear() {
    SDL_RenderClear(this->renderer);
}

void RenderWindow::RenderTexture(SDL_Texture* p_texture) {
    SDL_RenderCopy(this->renderer, p_texture, NULL, NULL);
}

// **mentioned method**
// takes const Entity& and renders it's texture
void RenderWindow::RenderEntity(const Entity& p_entity) {
    SDL_RenderCopy(this->renderer, p_entity.GetTexture(), NULL, NULL);
}

void RenderWindow::Display() {
    SDL_RenderPresent(this->renderer);
}

最后是entity.cpp

#include "entity.h"

Entity::Entity(Vec2i p_pos, SDL_Texture* p_texture)
    : pos(p_pos), texture(p_texture) {}

Entity::Entity()
    : pos(Vec2i{0, 0}), texture(NULL) {}

Entity::~Entity() {
    SDL_DestroyTexture(this->texture);
}

void Entity::SetPos(Vec2i p_pos) { this->pos = p_pos; }

const Vec2i& Entity::GetPos() const { return this->pos; }

void Entity::SetTexture(SDL_Texture* p_texture) { this->texture = p_texture; }

// used to get texture of entity to pass to renderer
SDL_Texture* Entity::GetTexture() const { return this->texture; }

void Entity::Move(Vec2i p_pos) {
    this->pos = p_pos;
}

void Entity::Move(size_t p_x, size_t p_y) {
    this->pos.x += p_x;
    this->pos.y += p_y;
}

我刚开始使用 SDL2,因此可能缺少一些明显的东西。如果您需要更多信息,请告诉我,我会尽力提供。

entities的创建需要一个临时的Entity,之后会被销毁。由于您没有实现复制构造函数,因此新实体留下了一个指向已释放对象的悬空指针。

最快的解决方法是将 Entity::texture 的类型更改为 std::shared_ptr<SDL_Texture>

或者,您可以创建移动构造函数并防止复制构造函数:

Entity::Entity(const Entity&) = delete;
Entity::Entity(Entity&& other)
  : pos(other.pos), texture(nullptr) {
  std::swap(texture, other.texture);
}