微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在SFML 2中使用精灵向量时,如何停止出现白色方块? 问题可能的解决方案

如何解决在SFML 2中使用精灵向量时,如何停止出现白色方块? 问题可能的解决方案

我正在尝试制作一个精灵矢量,但是前几个元素始终显示一个白色正方形。 变量包含在TileRPG类中,然后在main.cpp中使用 tile.cpp

void TileRPG::draw(int id,float x,float y,sf::RenderWindow& window) {
    m_sprite[id].setPosition(sf::Vector2f(x,y));
    window.draw(m_sprite[id]);
}


TileRPG::TileRPG() {
    std::ifstream file { "data/tileRPGList.rf" };
    std::string line{ "" },access { "" };
    sf::Texture texture;
    sf::Sprite sprite;
    unsigned int i = 0;

    while (std::getline(file,line)) {
        m_texture.push_back(texture);
        m_sprite.push_back(sprite);
        access = "data/" + line;
        m_texture[i].loadFromFile(access);
        m_sprite[i].setTexture(m_texture[i]);
        i++;
    }
}

tile.hpp

class Tile {
protected:
    std::vector<sf::Texture> m_texture;
    std::vector<sf::Sprite> m_sprite;
};

class TileRPG : public Tile {
public:
    TileRPG();
    void draw(int id,sf::RenderWindow& window);
};

解决方法

问题

来自sf::Sprite::setTexture() documentation

精灵不会存储它自己的纹理副本,而是保留指向您传递给该函数的指针的指针。

因此,sf::Sprite对象不存储sf::Texture对象的副本。顺便说一下,这与The Flyweight Pattern有关,因为它可以从sf::Sprite's documentation推断出来:

sf::Spritesf::Texture分开可以提供更大的灵活性和更好的性能:实际上,sf::Texture是一种繁重的资源,并且对其执行的所有操作都很慢(对于实时间应用程序)。另一方面,sf::Sprite是一个轻量级对象,可以使用sf::Texture的像素数据并使用其自己的transform / color / blending属性对其进行绘制。

您代码中的m_texture数据成员是sf::Texture个对象的向量,即 std::vector<sf::Texture> 。如果没有足够的容量来存储要插入的push_back()对象,则对其调用sf::Texture将重新分配向量的内部缓冲区。因此,存储在sf::Texture中的std::vector<sf::Texture>对象在调用push_back()之后可能最终位于内存中的其他位置。由于sf::Sprite对象仅保留指向sf::Texture对象的指针,因此如果sf::Texture对象已重新分配到内存中的其他位置,这些指针将最终指向内存中的错误位置。

可能的解决方案

您只需调用std::vector::reserve()即可为引导程序的内部缓冲区预先预留足够的内存。这种方法的缺点是,理想情况下,您需要预先知道向量将要存储的sf::Texture个对象的数量,以免浪费内存。

另一种方法是仅在正确填充sf::Sprite::setTexture()容器后之后调用std::vector<sf::Texture>。这样,由于您不会在向量中进一步插入sf::Texture个对象,因此不会重新分配其内部缓冲区。

最后,关于容器的另一种方法是将m_texture定义为std::vector<std::unique_ptr<sf::Texture>>。这样,如果发生向量的内部缓冲区的重新分配,则仅影响std::unique_ptr<sf::Texture>对象的地址, pointee 对象的地址,(即不是sf::Texture对象的地址)。您也可以将boost::stable_vector用于相同的目的。在这种情况下,您只需将m_texture定义为boost::stable_vector<sf::Texture>

,

Sprite::setTexture不会复制纹理,但会存储指向该纹理的指针。一旦纹理矢量将其指针重新分配到随后的push_back之一中,该指针便失效。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。