簡體   English   中英

在 SFML 2 中使用精靈向量時如何停止出現白色方塊?

[英]How to stop having a white square when using a sprite vector with 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++;
    }
}

瓷磚.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, float x, float y, sf::RenderWindow& window);
};

問題

來自sf::Sprite::setTexture()文檔

精靈不存儲它自己的紋理副本,而是保留一個指向您傳遞給此函數的指針。

因此, sf::Sprite對象不存儲sf::Texture對象的副本。 順便說一下,這與享元模式有關,因為它可以從sf::Sprite的文檔中推斷出來:

sf::Spritesf::Texture的分離允許更大的靈活性和更好的性能:確實sf::Texture是一種重資源,並且對它的任何操作都很慢(通常對於實時應用程序來說太慢了)。 另一方面,一個sf::Sprite是一個輕量級的對象,它可以使用sf::Texture的像素數據並用它自己的轉換/顏色/混合屬性來繪制它。

代碼中的m_texture數據成員是sf::Texture對象的向量,即std::vector<sf::Texture> 如果它沒有足夠的容量來存儲要插入的sf::Texture對象,則對其調用push_back()將重新分配向量的內部緩沖區。 因此,在調用push_back()后,存儲在std::vector<sf::Texture>sf::Texture對象可能最終位於內存中的不同位置。 由於sf::Sprite對象只保留指向sf::Texture對象的指針,如果sf::Texture對象已重新分配到內存中的其他位置,這些指針最終將指向內存中的錯誤位置。

可能的解決方案

您可以簡單地調用std::vector::reserve()為向量的內部緩沖區預先保留足夠的內存 這種方法的缺點是,理想情況下,您需要提前知道向量將要存儲的sf::Texture對象的數量,以避免浪費內存。

另一種方法是僅正確填充std::vector<sf::Texture>容器調用sf::Sprite::setTexture() 這樣,由於您不會進一步將sf::Texture對象插入向量中,因此它不會重新分配其內部緩沖區。

最后,關於容器的另一種方法是將m_texture定義為std::vector<std::unique_ptr<sf::Texture>> 這樣,如果重新分配向量的內部緩沖區發生,只有std::unique_ptr<sf::Texture>對象的地址受到影響,而不是指針對象的地址,(即,不是sf::Texture的地址sf::Texture對象)。 您也可以將boost::stable_vector用於相同的目的。 在這種情況下,您只需將m_texture定義為boost::stable_vector<sf::Texture>

Sprite::setTexture不會復制紋理,而是存儲指向它的指針。 一旦紋理向量在隨后的push_back之一中重新分配其存儲,該指針就會失效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM