【问题标题】:Initialize texture once for derived classes in sfml为 sfml 中的派生类初始化一次纹理
【发布时间】:2020-11-18 01:58:04
【问题描述】:

最近,我尝试使用纹理练习 SFML。但是,我遇到了一些问题。 SFML 网站告诉我,使用纹理最有效的方法是更新精灵。否则,我们的程序可能会消耗大量内存。我有一个基类和两个派生自它的其他类。如何初始化我的texture 变量,以便派生类可以将它与它们的精灵一起使用?我尝试在Base 类构造函数中初始化纹理并在派生类中调用它,但后来我意识到我的问题并没有解决,因为调用一个构造函数两次是无稽之谈。这个问题对我来说非常重要,因为我使用的状态模式会创建很多动态分配的对象。

#include <iostream>

class Base
{
protected:
    sf::Texture texture; //How to initialize this?
    sf::Sprite sprite;
public:
    Base();
};

class Derived1 : public Base
{
public:
    Derived1()
    {
        sprite.setTexture(texture);
    }
};

class Derived2 : public Base
{
public:
    Derived2()
    {
        sprite.setTexture(texture);
    }
};

【问题讨论】:

  • 如果texture 在多个实例中相同,为什么不将其设为static 字段?

标签: c++ textures sfml


【解决方案1】:

享元模式

SFML 网站告诉我,使用纹理最有效的方法是更新精灵。否则,我们的程序可能会消耗大量内存。

是的,sf::Spritesf::Texture 之间的关系对应于结构设计模式The Flyweight Pattern

sf::Texture 是一种 重量级 对象,我们希望尽可能共享其数据以节省内存。一个sf::Sprite 是一个flyweight 对象,多个sf::Sprite 对象可以引用同一个sf::Texture 对象来共享其数据。

sf::Sprite 仅包含特定于其所指纹理的特定用途的信息,例如纹理的位置、旋转、大小——这是外在状态。一个sf::Texture 对象包含可由多个sf::Sprite 对象共享的数据(即纹理图像本身)——这是所有引用的sf::Sprite 对象共享的内在状态到同一个sf::Texture

在 SFML 库中,您还可以找到带有 sf::Text/sf::Fontsf::Sound/sf::SoundBuffer 的这种模式。


不放弃享元

牢记上面公开的模式,您可能还想在设计中遵循它:

class Base {
public:
    Base(const sf::Texture& texture): sprite(texture) {}
protected:
    sf::Sprite sprite;
};

class Derived: public Base {
public:
    Derived(const sf::Texture& texture): Base(texture) {}
    // ...
};

sprite 数据成员通过引用传递给构造函数的sf::Texture 进行初始化,多个BaseDerived 对象可以共享相同的sf::Texture

举个例子:

sf::Texture myTexture;
myTexture.loadFromFile("myImageFile.png");

Base b1(myTexture), b2(myTexture);
Derived d1(myTexture), d2(myTexture);

b1b2d1d2 都共享同一个 sf::Texture 实例 – myTexture

当然,这些对象都不应该比myTexture 寿命长。

【讨论】:

  • @Thorvas 我建议将纹理对象放在外面(而不是作为数据成员)。然后,在初始化纹理之后,只需通过引用传递它来初始化精灵对象。如果您坚持将纹理对象作为数据成员,则应在构造函数的主体内调用sf::Texture::loadFromFile()
  • @Thorvas 这是将sf::Texture 对象作为非静态数据成员的结果:您实例化的包含类的每个实例都会创建一个sf::Texture 对象。
  • @Thorvas 这取决于你想要什么。如果将其声明为static,则所有BaseDerived 对象将共享同一个sf::Texture 对象。
  • @Thorvas 在这种情况下,我建议您改用 纹理管理器。看看this answer。然后,通过引用构造函数来传递纹理管理器。
  • @Thorvas 该错误可能是因为您没有为静态成员定义存储。请查看this post
猜你喜欢
  • 2020-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 2015-10-23
  • 2015-03-04
  • 2022-12-03
相关资源
最近更新 更多