无法使用 RenderTexture 创建精灵 [英] Cannot create a sprite using a RenderTexture

查看:48
本文介绍了无法使用 RenderTexture 创建精灵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个游戏,我创建了一个类来存储地图.我有一个函数来创建一个单独的精灵,在它上面绘制了所有可见的地图.我使用了 RenderTexture,然后我创建并返回了一个用它创建的精灵.然而,精灵是完全白色的.

I'm making a game, and I have created a class to store the map. I have a function to create a single sprite on which is drawn all the visible map. I've used a RenderTexture and then I create and return a sprite created with it. However, the sprite is completely white.

这里是地图生成和精灵绘制的代码

Here is the code for the map generation and the sprite draw

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),所以我无法理解发生了什么.

The problem seems to come from the map.draw part, as, if I use map.clear(Color::Red) before the double loop, the sprite stays white, but if I use sprite.setColor(Color::Red), it works. The fact is that the decor sprites are not covering the whole texture (the texture is 1920x1080, and the sprites 320x320), so I can't understand what's happening.

这不是装饰精灵加载,如果我使用 map.draw(Decor(GRASS)) 精灵显示正确.

This is not the decor sprite loading, if I use map.draw(Decor(GRASS)) the sprite is displayed correctly.

我尝试将指针用于 const_vector 和返回的精灵,但没有成功.

I've tried to use pointer for const_vector and for the returned sprite, whithout success.

推荐答案

使用 SFML 时的常见错误.

Popular mistake when using SFML.

Sprite Map::sprite()
{
    RenderTexture map;
    // ...
    Sprite sprite(map.getTexture());
    return sprite; 
}

map 是本地的.当函数结束时,map 被销毁.根据 官方教程/文档:

map is local. When function ends, map is destroyed. Sprite takes texture of map as shallow copy, it is only pointer to texture, according to 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.

所以,副本返回的精灵存储了悬空指针.这只是未定义的行为.

So, sprite returned by copy stores dangling pointer. It is just undefined behaviour.

1 天前发布的相关(我的)答案

解决方案:您必须将带有纹理的精灵包装在某种可深度复制的类中.您不能依赖浅层默认生成的复制操作.

Solution: you have to wrap sprites with textures in some kind of deep-copy-able class. You cannot rely on shallow defaulted generated copy operations.

这样的类可能看起来像:

Such a class could look like:

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

是安全的.

这篇关于无法使用 RenderTexture 创建精灵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆