gpt4 book ai didi

c++ - 绘制 Sprite 导致 Segmentation Fault

转载 作者:行者123 更新时间:2023-11-28 01:44:04 25 4
gpt4 key购买 nike

我正在用 SFML2 编写一个基于等距图 block 的简单游戏。 map 中的每个图 block 都由 Tile 类表示。该类包含 sf::Sprite 对象和 draw()应该在屏幕上绘制 Sprite 的函数。问题是调用 window.draw()导致段错误。我读到它通常是由关联的 sf::Texture 指针无效引起的,但我已经检查过,事实并非如此。

(使用 ResourceManager<sf::Texture> 对象将纹理引用传递给 Tile 构造函数)

瓷砖.hpp:

#pragma once

#include <SFML/Graphics.hpp>
#include "resource_manager.hpp"

class Tile
{
public:
Tile(const sf::Texture& texture);

void draw(sf::RenderWindow& window, const float dt);

private:
sf::Sprite _sprite;
};

瓷砖.cpp:

#include "tile.hpp"

Tile::Tile(const sf::Texture& texture)
{
_sprite.setTexture(texture);
}

void Tile::draw(sf::RenderWindow& window, const float dt)
{
std::cout << _sprite.getTexture()->getSize().x << std::endl; //Texture pointer works fine
window.draw(_sprite); //Segmentation Fault here
}

map .hpp:

#pragma once

#include <vector>
#include <SFML/Graphics.hpp>
#include "resource_holder.hpp"
#include "tile.hpp"

class Map
{
public:
Map(ResourceHolder& resources, int width, int height);

void draw(sf::RenderWindow& window, const float dt);

private:
ResourceHolder& _resources;
int _width, _height;

std::vector<Tile> _tiles;
};

map .cpp:

#include "map.hpp"
#include <iostream>

Map::Map(ResourceHolder& resources, int width, int height)
: _resources(resources), _width(width), _height(height)
{
_tiles.reserve(width * height);

for(int y = 0; y < _height; ++y)
{
for(int x = 0; x < _width; ++x)
{
_tiles[x + y * _width] = Tile(_resources.textures["groundTile_NE"]);
}
}
}

void Map::draw(sf::RenderWindow& window, const float dt)
{
for(int x = 0; x < _width; ++x)
{
for(int y = 0; y < _height; ++y)
{
_tiles[x + y * _width].draw(window, dt);
}
}
}

资源管理器.hpp:

#pragma once

#include <unordered_map>
#include <iostream>

template<typename Resource>
class ResourceManager
{
public:
ResourceManager(const std::string& directory, const std::string& extension)
: _directory("assets/" + directory + "/"), _extension("." + extension)
{}

Resource& operator[](const std::string& name)
{
return get(name);
}

Resource& get(const std::string& name)
{
if(!exists(name))
load(name);

return _resources.at(name);
}

bool exists(const std::string& name) const
{
return _resources.find(name) != _resources.end();
}

void load(const std::string& name)
{
Resource res;
if(!res.loadFromFile(_directory + name + _extension))
{
res.loadFromFile(_directory + "_fail_" + _extension);
}

_resources.insert({name, res});
}

private:
const sf::String _directory;
const sf::String _extension;

std::unordered_map<std::string, Resource> _resources;
};

最佳答案

从 SFML 源代码 (Graphics/Texture.cpp) 中,析构函数导致 OpenGL 纹理缓冲区被删除:

Texture::~Texture()
{
// Destroy the OpenGL texture
if (m_texture)
{
TransientContextLock lock;

GLuint texture = static_cast<GLuint>(m_texture);
glCheck(glDeleteTextures(1, &texture));
}
}

在您的load 方法中,您在堆栈上分配对象res。这意味着当方法返回时,将在 res 对象上调用 Resource 的析构函数。您的 OpenGL 句柄已删除,但仍存储在 res拷贝中,您将其插入到 _resources 中。

要解决此问题,请改为存储资源类的指针:

std::unordered_map<std::string, Resource*> _resources;

...

void load(const std::string& name)
{
Resource* res = new Resource();
if (!res->loadFromFile(_directory + name + _extension))
{
res->loadFromFile(_directory + "_fail_" + _extension);
}

_resources.insert({name, res});
}

Resource* operator[](const std::string& name)
{
return get(name);
}

Resource* get(const std::string& name)
{
if (!exists(name))
load(name); // or return nullptr

return _resources.at(name);
}

但是当 ResourceManager 对象被销毁时,您还需要销毁这些指针:

~ResourceManager()
{
for (auto& pair : _resources)
delete pair.second;
}

注意:您可能想将引用 存储在_resources 中。但见this link为什么那是不可能的。

关于c++ - 绘制 Sprite 导致 Segmentation Fault,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45943153/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com