1
\$\begingroup\$

I store 2D animation frames in some class. But the problem is that when I want to create multiple objects for example I want to spawn explosion or enemy

void ExampleScene::update()
{
    if (needToSpawnEnemy())
    {
        this->objects.add(Enemy());
    }
}

It means that everytime I want to spawn object I will need to access TextureHolder, pass string, get texture and load or compute animation frames and any other calculations that derivered object wants. It's not problem for example with player beacuse I load it on Scene::onCreate only once during entire game but with enemy I would do this during some update function.

My likewise simplifed implementation

struct Animation
{
public:
    void addFrame(Rect rect);
    //The rest of implementation
private:
    std::vector<Rect> frames;
}

class AnimatedSprite
{
public:
    void addAnimation(Animation& animation);
    //The rest of implementation
private:
    std::vector<Animation> m_animations;
}

How do I represent objects (this is gonna be very small project which will evolve later to ECS architecture but I think my problem will not change anyway so I want to solve it already)

struct Context
{
    TextureHolder textureHolder;
    //The rest of stuff...
}

class Object
{
public:
    //The rest of implementation
private:
    Context* context;
    AnimatedSprite sprite;
}

class Player : public Object { //implementation }
class Enemy : public Object { //implementation }

And how I add animation frames

void Enemy::onCreate()
{
    this->sprite.setTexture(this->context->textureHolder.getTexture("assets//graphics//enemy.jpg"));

    Animation walkAnimation;
    walkAnimation.addFrame({0, 0, 64, 64});
    walkAnimation.addFrame({64, 64, 64, 64}); //etc...
    //Surely it can be changed so frames will be loaded from file on disk

    this->sprite.addAnimation(walkAnimation)
}

Maybe NOW it's not very big problem unless I would get animation frames from file (which I want in future). So is there any gamedev standard / pattern / another aproach for this? I was thinking to store frames in dynamic memory and somehow share that data between objects of same class but I'm getting headache of thinking how I could manage that memory. (I don't see how smart pointers would help me beacuse there could not exist any Enemy objects for some time)

class AnimatedSprite
{
public:
    void setAnimation(Animation* animation)
    //The rest of implementation
private:
    AnimationState* animationState;
    AnimationFrames* animationFrames;
}

Should first object load everything but how do I delete it? I don't know if x enemy will be last one. Or maybe should I add some methods to Object class

virtual void Object::loadDataFromDisk();
virtual void Object::unloadDataFromDisk();

But it seems to be bit clumsy. I was also thinking to use my Context class to create somewhat AnimationHolder and use it like this->context->animationHolder.getAnimation("ENEMY_WALK"); but I'm not sure about this.
Or maybe some prefab system? TLDR; To be precise my shorter question is how to avoid loading same 2D frames data (not textures) while spawning new objects.

So any help and ideas?

\$\endgroup\$
0

1 Answer 1

0
\$\begingroup\$

I do not know if you have a Renderer class that can store global rendering objects like textures, fonts, shaders, materials, etc. The simplest implementation with what you have right now is to have your AnimatedSprite class be the owner for all your animations (i.e. the one class responsible for creating/deleting them) via: static std::map<std::string, std::unique_ptr<AnimatedSprite>> s_registry (or, if you want to be cache friendly: static std::vector<std::pair<std::string, std::unique_ptr<AnimatedSprite>>>), and the entities just need to store a pointer to one of them.

As for loading, I use a custom XML format that the Animated Sprite can use to parse during loading that will automatically add it to the registry. By generalizing the XML format you can have it just be part of an entity's own XML format, when that part gets parsed, the animation is loaded into the registry and a reference to the newly created animation is added to the entity.

\$\endgroup\$
1
  • \$\begingroup\$ I don't have any "Renderer", I use SFML and store my textures, fonts in separate classes for example TextureHolder etc. then I put every "Holder" to Context struct and I supply every object / scene with a pointer to Context. Anyway if I understanded you well your idea sums up to use my Context class and create AnimationHolder (which I think will be more elegant than use AnimatedSprite to store all animations since this class isn't actually supposed to do that) \$\endgroup\$
    – Eminiox PL
    May 27, 2021 at 21:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .