简体   繁体   English

SDL2 无法从矢量渲染实体

[英]SDL2 cannot render entities from vector

Rendering individual textures was no problem at all, though after i wrapped these textures in an entity class, and put these in a vector, things just didn't work anymore (renders black screen).渲染单个纹理完全没有问题,但在我将这些纹理包装在一个实体 class 中,并将它们放入一个向量中后,事情就不再起作用了(呈现黑屏)。 Anyone got a clue why?有人知道为什么吗?

main.cpp主.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渲染窗口.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);
}

and finally entity.cpp最后是 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;
}

The creation of entities requires a temporary Entity , which is destroyed afterwards. entities的创建需要一个临时的Entity ,然后将其销毁。 Since you did not implement a copy constructor, this leaves the new Entity with a dangling pointer to a freed object.由于您没有实现复制构造函数,因此新实体将带有一个指向已释放 object 的悬空指针。

The quickest fix is to change the type of Entity::texture to std::shared_ptr<SDL_Texture> .最快的解决方法是将Entity::texture的类型更改为std::shared_ptr<SDL_Texture>

Alternatively, you can create a move constructor and prevent copy constructors:或者,您可以创建一个移动构造函数并阻止复制构造函数:

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

The simplest way was to remove the destructor from the entity class.最简单的方法是从实体 class 中删除析构函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM