gpt4 book ai didi

c++ - SFML 纹理显示为白色框

转载 作者:太空狗 更新时间:2023-10-29 21:19:15 25 4
gpt4 key购买 nike

我在基类中有一个纹理和 sprite 正在被另一个类扩展,但是在绘制时,sprite 显示为一个白色框。我知道这与 Sprite 失去它与纹理对象的链接有关,但我是 C++ 的新手,所以我不太确定这是怎么发生的。

这是代码(我删除了一些不相关的部分以减小大小):

皮卡.h:

#ifndef PICKUPS_PICKUP_H
#define PICKUPS_PICKUP_H

#include <SFML\Graphics.hpp>
#include "..\Player.h"

namespace Pickups
{
class Pickup
{
private:
sf::Vector2f position;
sf::Texture texture;
sf::Sprite sprite;
public:
Pickup();

bool drop(float dt);
void draw(sf::RenderWindow* window);

void setTexture(sf::String name);

void setPos(sf::Vector2f position);
sf::Vector2f getPos();

void isColliding(Player* player);

virtual void onCollect(Player* player) = 0;
};
}

#endif

皮卡.cpp:

#include "Pickup.h"

namespace Pickups
{
Pickup::Pickup()
{
}

void Pickup::draw(sf::RenderWindow* window)
{
window->draw(sprite);
}

void Pickup::setTexture(sf::String name)
{
if (!texture.loadFromFile("images/pickups/" + name + ".png"))
std::cout << "Error loading image: images/pickups/" + name.toAnsiString() + ".png" << std::endl;
else
sprite.setTexture(texture);
}
}

健康.h:

#ifndef PICKUPS_HEALTH_H
#define PICKUPS_HEALTH_H

#include "Pickup.h"

namespace Pickups
{
class Health : public Pickup
{
private:
int worth;
public:
Health(sf::Vector2f position, int worth);
void onCollect(Player* player);
};
}

#endif

健康.cpp:

#include "Health.h"

namespace Pickups
{
Health::Health(sf::Vector2f position, int worth)
{
setTexture("health");
setPos(position);
this->worth = worth;
}

void Health::onCollect(Player* player)
{
player->addLives(worth);
}
}

(我不知道这是否是问题的一部分,但我也可以发布它)我将拾音器存储在一个 vector 中,如下所示:

std::vector<Pickups::Health> pickups;

最佳答案

A std::vector复制或移动插入的元素,所以只要您有默认的复制构造函数,或者只要您不更改这种肮脏的 每个元素一个纹理 样式,(元素只需要有一个公共(public)的纹理对象实际指向,所以你浪费了很多内存) sf::Sprite 的指针对象持有的纹理变得无效。要了解为什么我们需要考虑插入时会发生什么:

你设置了一个很好的Pickup ish 对象并将其添加到调用复制构造函数的 vector 中。假设您想添加的漂亮对象是对象 A现在添加/复制的对象是 B .两者都有 Sprite S和纹理 T .两种纹理都有效,但问题是:AS指向 AT , 所以在将其复制到 B 之后BS还指向 AT !正如我假设 A只是暂时的,所以它连同它的纹理一起被破坏,然后你就拥有了它,一个漂亮的白色盒子。

你可以用其他一些肮脏的方式解决这个问题,比如在 Pickup 中创建你自己的复制构造函数像这样:

Pickup::Pickup(const Pickup& other)
: position(other.position), texture(other.texture), sprite(other.sprite)
{ sprite.setTexture(texture); }

或通过存储 std::unique_ptr<Pickups::Health>的,而不仅仅是 Pickups::Health的。

然而,您应该使用某种更好的方法 Resourcemanager ,它只存储所有相关的纹理,理想情况下是一个,一个大的 tileset,因为加载一次但大的比加载多个但小的纹理更快。您可以编写自己的非常简单的管理器或使用其他一些管理器,例如来自伟大的 Thor 图书馆。要将特定图 block 设置为 Sprite 的纹理,只需调用 sf::Sprite::setTextureRect .


我想提一下您设计的一些额外改进。让Pickup派生自 sf::Drawable并定义其纯虚拟 draw函数,您可以将其设为私有(private)。因此你来自 Pickup派生对象不需要知道任何 sf::RenderTarget你可以做 target.draw(myPickupObject) .

不用存储位置,让Pickup即可派生自 sf::Transformable , 也。您不必实现任何功能,您唯一需要做的就是将矩阵应用于 sf::RenderStates传递给 draw 的对象.

您的总体 draw函数可能如下所示:

void Pickup::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
//'applying' transformation-matrix
states.transform *= getTransform();

target.draw(sprite, states);
}

所以你的 Pickup现在只有sf::Sprite作为成员(member)和整体,您的标题只需要包含 SFML/Graphics/Sprite.hpp .

关于c++ - SFML 纹理显示为白色框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27951870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com