无法使用 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

安全。