为什么纹理显示不正确?

Why textures don't display properly?

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

class header 带有向量保持纹理

    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];
}

与 child class 精灵:

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() 函数之后在堆上创建精灵 object。

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

如下所述解决。

getTextureByID() return 是纹理的副本,而不是参考。这个副本在超出范围时被销毁 - 所以一旦对 sprite.setTexture() 的调用完成。
这导致 Sprite 具有指向不再存在的纹理的指针。

解决方案是 return 来自 getTextureByID() 的指针或引用。在我们更改该函数的同时,我们还应该使函数和 returned 值 const 因为我们不打算修改它,尽管这是可选的 - 这是一个好习惯我不妨指出出。

这是一个 const 函数的例子,它 return 是 const reference:

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

这有望解决您的问题。


不相关的注释:

您的纹理 class 总共存储了 四个 个纹理,两个 个泥土纹理,两个草纹理。
这可能是您想要的,也可能不是。
一种解决方案是没有成员变量 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<std::string, std::unique_ptr<sf::Texture>>)