无法使用 RenderTexture 创建精灵
Cannot create a sprite using a RenderTexture
我在做游戏,我创建了一个class来存储地图。我有一个功能来创建一个单一的精灵,在其上绘制所有可见地图。我使用了 RenderTexture,然后创建并 return 使用它创建的精灵。然而,精灵是完全白色的。
这是地图生成和精灵绘制的代码
void Map::procedural_generate()
{
cout << "Starting the map generation" << endl;
int generation_max = m_size.x * m_size.y,
current_generation = 0;
vector<Decor> decor_vector;
m_decor_vector.clear();
const vector<Decor> const_vector
{
Decor(GRASS)
};
for (int i = 0; i < m_size.x; i++)
{
decor_vector.clear();
for (int j = 0; j < m_size.y; j++)
{
decor_vector.push_back(const_vector[GRASS]);
decor_vector[j].set_position(Vector2f(i * 32, j * 32));
current_generation++;
cout << "Generation : " << current_generation << '/' << generation_max << '\r';
}
m_decor_vector.push_back(decor_vector);
decor_vector.clear();
}
cout << "Map generation has ended" << endl;
}
Sprite Map::sprite()
{
RenderTexture map;
if (!map.create(WINDOW_WIDTH, WINDOW_HEIGTH))
cout << "Map : Unable to create the RenderTexture" << endl;
map.clear(Color::Green);
for (int i = 0; i < m_size.x; i++)
for (int j = 0; j < m_size.y; j++)
map.draw(m_decor_vector[i][j].sprite());
map.display();
Sprite sprite(map.getTexture());
return sprite;
}
问题似乎出在map.draw部分,因为,如果我在双循环之前使用map.clear(Color::Red)
,精灵保持白色,但如果我使用sprite.setColor(Color::Red)
,它作品。事实上,装饰精灵没有覆盖整个纹理(纹理是 1920x1080,而精灵是 320x320),所以我不明白发生了什么。
这不是装饰精灵加载,如果我使用 map.draw(Decor(GRASS))
精灵显示正确。
我已经尝试为 const_vector
和 returned sprite 使用指针,但没有成功。
使用 SFML 时的常见错误。
Sprite Map::sprite()
{
RenderTexture map;
// ...
Sprite sprite(map.getTexture());
return sprite;
}
map
是本地的。当函数结束时,map
被销毁。 Sprite 将 map
的纹理作为浅拷贝,它只是指向纹理的指针,根据 official tutorial/documentation:
The white square problem
You successfully loaded a texture, constructed a sprite correctly, and... all you see on your screen now
is a white square. What happened?
This is a common mistake. When you set the texture of a sprite, all it
does internally is store a pointer to the texture instance. Therefore,
if the texture is destroyed or moves elsewhere in memory, the sprite
ends up with an invalid texture pointer.
因此,复制返回的精灵存储了悬挂指针。这只是未定义的行为。
解决方案:您必须以某种可深度复制的方式用纹理包裹精灵 class。
您不能依赖浅层默认生成的复制操作。
这样的 class 可能看起来像:
class TexturedSprite {
public:
sf::Sprite sprite;
sf::Texture texture;
TexturedSprite() {
init(); // load texture
}
void init() {
// load texture
texture.loadFromFile("texture1.png");
sprite.setTexture(texture);
sprite.setPosition(0,0);
}
TexturedSprite(const TexturedSprite& theOther) {
texture = theOther.texture; // deep copy
sprite.setTexture(texture);
}
TexturedSprite& operator=(const TexturedSprite& theOther) {
if (this == &theOther)
return *this;
texture = theOther.texture; // deep copy
sprite.setTexture(texture);
return *this;
}
};
然后代码:
TexturedSprite fooMain;
{
TexturedSprite foo; // local
fooMain = foo;
} // foo is destroyed, but = did deep copy of texture
安全。
我在做游戏,我创建了一个class来存储地图。我有一个功能来创建一个单一的精灵,在其上绘制所有可见地图。我使用了 RenderTexture,然后创建并 return 使用它创建的精灵。然而,精灵是完全白色的。
这是地图生成和精灵绘制的代码
void Map::procedural_generate()
{
cout << "Starting the map generation" << endl;
int generation_max = m_size.x * m_size.y,
current_generation = 0;
vector<Decor> decor_vector;
m_decor_vector.clear();
const vector<Decor> const_vector
{
Decor(GRASS)
};
for (int i = 0; i < m_size.x; i++)
{
decor_vector.clear();
for (int j = 0; j < m_size.y; j++)
{
decor_vector.push_back(const_vector[GRASS]);
decor_vector[j].set_position(Vector2f(i * 32, j * 32));
current_generation++;
cout << "Generation : " << current_generation << '/' << generation_max << '\r';
}
m_decor_vector.push_back(decor_vector);
decor_vector.clear();
}
cout << "Map generation has ended" << endl;
}
Sprite Map::sprite()
{
RenderTexture map;
if (!map.create(WINDOW_WIDTH, WINDOW_HEIGTH))
cout << "Map : Unable to create the RenderTexture" << endl;
map.clear(Color::Green);
for (int i = 0; i < m_size.x; i++)
for (int j = 0; j < m_size.y; j++)
map.draw(m_decor_vector[i][j].sprite());
map.display();
Sprite sprite(map.getTexture());
return sprite;
}
问题似乎出在map.draw部分,因为,如果我在双循环之前使用map.clear(Color::Red)
,精灵保持白色,但如果我使用sprite.setColor(Color::Red)
,它作品。事实上,装饰精灵没有覆盖整个纹理(纹理是 1920x1080,而精灵是 320x320),所以我不明白发生了什么。
这不是装饰精灵加载,如果我使用 map.draw(Decor(GRASS))
精灵显示正确。
我已经尝试为 const_vector
和 returned sprite 使用指针,但没有成功。
使用 SFML 时的常见错误。
Sprite Map::sprite()
{
RenderTexture map;
// ...
Sprite sprite(map.getTexture());
return sprite;
}
map
是本地的。当函数结束时,map
被销毁。 Sprite 将 map
的纹理作为浅拷贝,它只是指向纹理的指针,根据 official tutorial/documentation:
The white square problem You successfully loaded a texture, constructed a sprite correctly, and... all you see on your screen now is a white square. What happened?
This is a common mistake. When you set the texture of a sprite, all it does internally is store a pointer to the texture instance. Therefore, if the texture is destroyed or moves elsewhere in memory, the sprite ends up with an invalid texture pointer.
因此,复制返回的精灵存储了悬挂指针。这只是未定义的行为。
解决方案:您必须以某种可深度复制的方式用纹理包裹精灵 class。 您不能依赖浅层默认生成的复制操作。
这样的 class 可能看起来像:
class TexturedSprite {
public:
sf::Sprite sprite;
sf::Texture texture;
TexturedSprite() {
init(); // load texture
}
void init() {
// load texture
texture.loadFromFile("texture1.png");
sprite.setTexture(texture);
sprite.setPosition(0,0);
}
TexturedSprite(const TexturedSprite& theOther) {
texture = theOther.texture; // deep copy
sprite.setTexture(texture);
}
TexturedSprite& operator=(const TexturedSprite& theOther) {
if (this == &theOther)
return *this;
texture = theOther.texture; // deep copy
sprite.setTexture(texture);
return *this;
}
};
然后代码:
TexturedSprite fooMain;
{
TexturedSprite foo; // local
fooMain = foo;
} // foo is destroyed, but = did deep copy of texture
安全。