0
\$\begingroup\$

I have a problem with my sprite animations right now. I have different animations and sequences for each character so an specific archer might do a ranged attack in which he just plays one animation and shoots an arrow at the enemy. The other might be melee and has to move close to the enemy while having an animation for that and when he reaches the enemy do its attack animation and return back to its original position also having its own animation. And I could go on and on for maybe like bosses etc.

As you can see there are many possible animation sequences for quite a variety of characters. My question is what is the best way to program this into my game. Should I have a base class for the battler which has all the common methods and than inherent each character from that class with its own attack sequences? Because that is what I thought of first but I'm affraid its the wrong approach since I will have many classes doing the same kind of sequences. Or maybe should I create a sequence base class and each different animation sequence will inherent from that class. Than play the sequence on the base Battler class?

I'm developing the game in SFML C++ and here is a gif of the battle screen right now so you can get an idea of how a battle is in my game.

Battle scene of my game

\$\endgroup\$
1
\$\begingroup\$

The animations and logic for attacks can be broken down into individual logical units and then sequenced via data files. For example, you might have code like this:

AdvanceBehavior(entity, target, speed)
FallbackBehavior(entity, target, speed)
SoundBehavior(entity, sound_id)
AnimateBehavior(entity, anim_id, speed)

and then you can have a data file that specifies how attacks are sequenced:

{
  {
    'name': "fire arrow",
    'sequence': [
      {'id': 'sound', 'sound_id': 'twang.wav'},
      {'id': 'animate', 'anim_id': 'elf_fire_arrow.anim', 'speed': 1.0},
    ]
  },
  {
    'name': "fast strike",
    'sequence': [
      {'id': 'animate', 'anim_id': 'elf_jump.anim', 'speed': 2.0},
      {'id': 'sound', 'sound_id': 'jump.wav'},
      {'id': 'advance', 'speed': 5.0},
      {'id': 'animate', 'anim_id': 'elf_smack.anim', 'speed': 2.0},
      {'id': 'sound', 'sound_id': 'thwack.wav'},
      {'id': 'fallback', 'speed': 1.0},
      {'id': 'animate', 'anim_id': 'elf_jump.anim', 'speed': 1.0},
    ]
  }
}

Your code should contain logic. Your data should contain configuration.

\$\endgroup\$
  • \$\begingroup\$ Oh, I see what you mean. I'm going to try this, thank you. \$\endgroup\$ – Arthur Jun 20 '16 at 7:43
1
\$\begingroup\$

Should I have a base class for the battler which has all the common methods and than inherent each character from that class with its own attack sequences?

If you have a lot of battler types, I don't think you would necessarily want them all to be their separate class if they are very similar to each other otherwise. One approach would be to have them all be of a single type, Battler, with lists of abilities and animations and sprites and what-not attached to them after construction.

Instead of using separate child classes' constructors to then construct the different types of battlers, you could create simple functions that construct a suitable battler for you instead. For example:

Battler createBattlerType1()
    {
    Battler battler;

    //Add animations, abilities, etc.

    return battler;
    }

Or maybe should I create a sequence base class and each different animation sequence will inherent from that class. Than play the sequence on the base Battler class?

To some extent, that sounds like a sensible thing to do to me, however, again I don't think you necessarily need to mix in inheritance at all. If a "sequence of animations" is simply a list of animations to be played one after another, you don't necessarily even need to create a new datatype for it: you could just store it in, say, an array or an std::vector. Then, each "battler" instance could have it's own list of animation sequences appointed to it.

\$\endgroup\$
  • \$\begingroup\$ What I mean with sequence is for example the melee character moves close to the enemy with an animation than doing its attack animation and finally go back to its original position. I need to code for example the movement to the enemy and back or a arrow flying to the enemy and doing damage. The full attack is an sequence. \$\endgroup\$ – Arthur Jun 18 '16 at 13:56
  • \$\begingroup\$ @Arthur: and those behaviors can be individual pieces of logic (advance, attack, fire, retreat, etc.) sequenced together via data. And the animations associated with the sequence like in data. You can have a Battler class that contains a list of BattleSequence instances, each containing a list of BattleAction instances that contain a reference to a Behavior, an Animation, etc. All data-driven, extensible, etc. Try to get in the habit of preferring data over code when possible. Putting everything in code eventually turns into an unmaintainable buggy copy-n-paste mess. \$\endgroup\$ – Sean Middleditch Jun 18 '16 at 23:00
  • \$\begingroup\$ @SeanMiddleditch So would every Behavior of a BattleAction be a piece of code, for example the sprite moving to the enemy which ofc could be reused. Or do you mean with data driven a non code based approach like storing information in an xml file? \$\endgroup\$ – Arthur Jun 19 '16 at 0:11
  • \$\begingroup\$ @Arthur: explaining adequately is complicated enough that I put it in a new answer. \$\endgroup\$ – Sean Middleditch Jun 20 '16 at 5:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.