我有这个课程为我的游戏添加精灵:
\x10
我使用Pickup nameSprite()为我的游戏添加另一个精灵。但每次我这样做(我尝试使用不同的图像,我使用class Pickup {
public:
Pickup::Pickup()
{
Texture healthTexture;
healthTexture.loadFromFile("health.png");
m_Sprite.setTexture(healthTexture);
}
Sprite Pickup::getSprite()
{
return m_Sprite;
}
private:
Sprite m_Sprite;
};
来查看问题是否与图像有关)我只看到一个白色矩形而不是我想要的东西,似乎没有任何错误。我的问题是:链接问题的原因是什么?
答案 0 :(得分:1)
纹理参数指的是必须存在的纹理 精灵使用它。实际上,精灵并没有存储自己的副本 纹理,而是保持指向您传递给它的指针 这个功能。如果源纹理被破坏并且精灵尝试 使用它,行为是未定义的。
您创建和加载的纹理对象是构造函数的本地对象并在其末尾被销毁,因此一旦在程序执行中稍后实际使用它,Sprite-Object保留的指针/引用就会悬空。
为避免此问题,您可以将纹理另存为Pickup类中的其他成员。
正如Lorence Hernandez在下面的一篇富有洞察力的评论中指出的那样,这不是一个非常好的主意。每个Pickup实例都会拥有自己的纹理实例,尽管纹理相同,浪费内存。此外,Pickup无法再使用默认的复制操作,因为复制的Pickup的Sprite实例随后会引用原始对象中的纹理实例。
更好的方法是在Pickup类本身之外移动处理这个问题,即纹理实例的管理及其生命周期。 有许多可能的解决方案,从执行内部缓存的简单函数到更复杂的资源管理器类。
前者可以像下面的代码片段一样简单:
const Texture& load(const std::string &filename)
{
static std::map<std::string,std::unique_ptr<Texture>> textures;
auto &tex_ptr=textures[filename];
if(!tex_ptr)
tex_ptr=std::make_unique<Texture>(filename);
return *tex_ptr;
}
当然,这个简单的版本确实存在轻微的“泄漏”,因为在程序执行期间永远不会释放未使用的纹理。
谷歌搜索“纹理管理器sfml”将产生许多关于后者的示例和教程,例如SFML的github中的this rather old unofficial one。它管理sf :: Image,而不是sf :: Texture,但是同样的一般想法适用。