So far we’ve covered what animations are and how to organize them into logical groupings, now we’ll discuss how to go about applying an animation to a sprite to achieve playback.
Reusability
One important thing I want to achieve in building Hikari as a data-driven game is reusability — being able to define an object once and use it many times without the overhead of duplication.
Think about this: you have 10 enemies on the screen all of the same type. All 10 of the enemies will be playing the same animation, the only difference being that each enemy may be playing a different part of the animation at any point in time. It doesn’t make sense to have 10 copies of the animation when really only a single animation is being played.
Solving this problem is easy: separate the animation data from the playback mechanism. Then you can:
- Share instances of
Animation
objects - Play different parts of the same animation without duplicating it
We’ve already defined our Animation
class which solves the animation data part of the problem. So let’s create an Animator
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|
Notice that Animator
has virtual
functions; it is a base class. The reason? It’s possible that we could “apply” an animation to something in a different way but the playback mechanism will remain the same. In this way we can subclass Animator
and adapt playback for different kinds of things.
Also notice that there is a private “playing” method: void play(float delta)
. This is where the core playback functionality is at, and that logic should work the same way for all types of Animator
s. Keep it secret, keep it safe.
Let’s say that we want to be able to reuse Animation
objects between game objects and elements of our GUI. It’s easy to do this by subclassing Animator
into more specialized classes: SpriteAnimator
and GUIIconAnimator
.
For sprites all we need to do is change what frame it’s displaying as the animation plays. We do this by changing it’s “source rectangle”, or which area of its source image is displays when rendered.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
As you can see, this kind of separation makes using Animation
objects in different ways easy. You can imagine how GUIIconAnimator
might work, assuming a gui::Icon
can have it’s “source rectangle” changed. We use this design for animation playback in Hikari – and animations are shared by game objects and GUI elements.
If you’re ever building an animation system, consider decoupling the animation data from the playback mechanism.