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);
}
我使用 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);
}