At the heart of any great platformer is good quality animation, and Mega Man games deliver on that front. Due the the technical limitations of the NES the programmers at the time had to get pretty creative with how they represent sprites and animations.
Luckily for us today computer technology has come a long way and we have the luxury of focusing on solving programming tasks without worrying as much about our hardware limitations.
So let’s talk about animations.
Since I wanted fine-grained control over many aspects of the animation I had a few requirements for how I wanted them to be stored and used within the game. Some things I thought about were:
- Frame dimensions may vary
- Frame durations may vary
- Some animations may repeat
- Some animations may have a “beginning” and a “looping” part
An animation is really a sequence of images (referred to as “frames” from here on) and some data describing how they are displayed. So let’s define a frame:
- A frame is simply a rectangle, an origin (or “hotspot”), and a display time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
The “source rectangle” is the region of an image or texture to use when displaying this frame.
The “hot spot” is an offset from the top-left of the source rectangle that can be used to “move” a frame when displaying it. This is useful if the frames of an animation are not all the same size or the subject is not always in the same relative location within a given frame.
The “display time” is how long the frame should be displayed. In Hikari’s case display time is expressed in seconds where
1.0fis one second.
Now that frames are covered we can focus on the remaining aspects of animations: whether they repeat or not, and if they do, do they start from the beginning or somewhere else?
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
If an animation repeats there is a chance that you may want to play some sort of “introductory” part and then loop over another part indefinitely. This could be handled by using two different animations and playing them in sequence, but then you run into problems having to define the sequences of animations to play and when to play them, etc. It’s a common enough case that I felt baking it into
Animation was the right thing to do…
…and that’s what
keyframe is for.
keyframe is the frame to start playback from when it repeats. If the
keyframe is set to
0 then the entire animation will play from the beginning when it repeats. Let’s say, though, that you have a 9-frame animation of Mega Man running. The first 3 frames show him just starting to move, while the remaining 6 frames show him fully running. You can use a single
Animation with a
keyframe of 2 (since frame indicies are 0-based) and you’re all set. Then animation will play frames
0-8 the first time through, and then
2-8 any subsequent time until the playback is restarted. Cool.
There’s one other thing that’s important to think about: how does one handle transitioning between two animations? Should they always restart from the beginning when you change from one to the other? What about in the case where you have a
running + shooting animation? The transition between those two should not cause playback to restart — so how do we handle that? That’s where the
syncGroup comes in to play.
The concept of sync groups is simple: animations in the same sync group have identical playback characteristics, animations in different sync groups do not. The sync group is a marker to indicate that there is no need to reset playback when transitioning between animations in the same group. Any time you transition, check if the previous and next animations are in the same sync group. If they are, don’t reset playback. If they aren’t, then start playing from the beginning of the new animation.
Of course, sync groups have their drawbacks. The biggest being that it’s still up to someone to make sure that animations with the same sync group are actually indentical, frame-wise.
Since our data is
JSON it’s easy to represent animations in a structured way. Here’s a simple 2-frame, repeating animation:
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
An animation with many frames written this way can get a little bit lengthy but the definitions are still very readable and I would prefer this over
Next installment we’ll talk more about grouping animations together as well as how we go about actually playing them.