为什么纹理显示不正确?
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_Texture
和 grass_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>>
)
我有一个项目,我的纹理在 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_Texture
和 grass_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>>
)