【问题标题】:Why textures don't display properly?为什么纹理不能正确显示?
【发布时间】:2021-04-06 21:28:54
【问题描述】:

我有一个项目,我的纹理没有正确显示在窗口内。它总是显示空白的白色精灵而不是纹理。我无法找出我做错了什么。这是我的代码:

带有矢量保存纹理的类头

    class textures
    {
    public:
        sf::Texture dirt_Texture;
        sf::Texture grass_Texture;
        std::vector<sf::Texture> texturesVector;
        /*
             dirt = 0
            grass = 1
        */
    public:
        textures();

    sf::Texture getTextureByID(int id);



};

和它的 .cpp 文件:

//constructor populate vector with textures
textures::textures()
{
    if (!dirt_Texture.loadFromFile("dirt.PNG"))
    {
        std::cout << "Error while loading texture.\n";
    }
    dirt_Texture.isSmooth();
    texturesVector.push_back(dirt_Texture);

    if (!grass_Texture.loadFromFile("grass.PNG"))
    {
        std::cout << "Error while loading texture.\n";
    }
    texturesVector.push_back(grass_Texture);
    std::cout << "Texture constructor has been called.\n";
}

sf::Texture textures::getTextureByID(int id)
{
    return texturesVector[id];
}

带有子类精灵:

class sprites : public textures
{
private:
    //textures* textureClass;
    sf::Sprite sprite;
    std::vector<int> textureIDsVector;
public:
    sprites();
    ~sprites();

    int getVectorValueAtLine(int &line);
    void setVectorValueAtLineTo(int &line, int value);
    void updateTextureAtLine(int& line);
    sf::Sprite* getSprite();

};

主函数在 .cpp 中的位置

sprites::sprites()
{
    std::vector<int> cubeIDsVector(100, 0);
    textureIDsVector = cubeIDsVector;
    //textureClass = new textures();
    std::cout << "Sprite constructor has been called.\n";
}

void sprites::updateTextureAtLine(int& line)
{
    switch (textureIDsVector[line])
    {
    case 0:
        //switcher = 0;
        sprite.setTexture(getTextureByID(0));
        sprite.setColor(sf::Color(55, 150, 150, 150));
        std::cout << "case 0\n";
        break;
    case 1:
        //switcher = 1;
        sprite.setTexture(getTextureByID(1));
        sprite.setColor(sf::Color(155, 50, 150, 150));
        std::cout << "case 1\n";
        break;
    default:
        break;
    }
}

在主循环中,我在 sf::RenderWindow 之后和 window.clean(...) 从 for 循环调用 updateTextureAtLine() 函数之后在堆上创建精灵对象。

没有返回错误,在调试时似乎也很好,我是新手,但看起来纹理总是在内存中,我无法找出问题所在。

如下所述解决。

【问题讨论】:

    标签: c++ sprite sfml stdvector


    【解决方案1】:

    getTextureByID() 返回纹理的副本而不是引用。此副本在超出范围时将被销毁 - 所以只要对 sprite.setTexture() 的调用完成。
    这会导致 Sprite 有一个指向不再存在的纹理的指针。

    解决方案是从getTextureByID() 返回一个指针或引用。虽然我们正在更改该函数,但我们也应该将函数和返回值设为 const,因为我们不打算修改它,尽管这是可选的 - 我不妨指出这是一个好习惯。

    这是一个返回 const referenceconst 函数示例:

    // header
    const sf::Texture& getTextureByID(int id) const;
    // source
    const sf::Texture& textures::getTextureByID(int id) const {
        return texturesVector[id];
    }
    

    这有望解决您的问题。


    不相关的笔记:

    您的纹理类总共存储 四个 纹理、两个 泥土纹理和 两个 草纹理。
    这可能是您想要的,也可能不是。
    一种解决方案是没有成员变量dirt_Texturegrass_Texture,或者只是没有texturesVector
    另一种解决方案是让texturesVector 存储指向纹理的指针,这些指针也可以是const,如下所示:

    // header
    std::vector<const sf::Texture*> texturesVector;
    // source
    //   constructor
    texturesVector.push_back(&dirt_Texture);
    ...
    texturesVector.push_back(&grass_Texture);
    //   getTextureByID()
    return *texturesVector[id]; // (or alternatively return a pointer)
    

    最后,如果您将纹理对象存储在 texturesVector 内(如果您切换到指针,这不会有问题),请注意添加更多纹理可能会强制矢量的内部数组更改内存位置从而使您的纹理无效。
    如果您不打算在运行程序的中途添加更多纹理,那没关系。我确实在运行程序的中途添加了很多纹理,因为我喜欢延迟初始化。如果您计划添加更多纹理,则要么使用另一个不移动其对象的容器,要么为您的纹理动态分配一个位置。我是后者的粉丝,使用字符串映射到纹理的唯一指针 (std::unordered_map&lt;std::string, std::unique_ptr&lt;sf::Texture&gt;&gt;)

    【讨论】:

    • 所以如果我把 sf::Texture 污垢_Texture 和 sf::Texture Grass_Texture;对于纹理构造函数,调用构造函数后它将消失,并且向量中仅存储两个纹理。对吗?
    • 等。主要问题已解决,非常感谢您:-)
    • 是的,将sf::Texture dirt_Texturesf::Texture grass_Texture 移入纹理构造函数应该使它们只存储在向量中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多