Thursday, August 3, 2017

The global animation system, part 2

In order to keep track of an object's animation across several frames, animation functions do a lot of extra bookkeeping within the object's SST, beyond the animation value in byte $20. Objects should not mess with these values, or they run the risk of throwing the function's internal state off the rails and setting the whole game on fire.

  • $21 is the previous animation, and holds the value $20 had during the previous execution of the animation function. This is used to detect external changes to the current animation.
  • $22 is the mapping frame, as we already know. It's safe to change this one, but it will be changed back the next time the animation frame is incremented.
  • $23 is the animation frame. This is the current step in the animation. It starts at 0 and is incremented when the animation frame timer exceeds the wait value in the first byte of the animation's definition.
  • $24 is the animation frame timer. This is how long the animation function has waited for during the current animation frame. It starts at 0 and is incremented once per frame.

In the previous entry, I glossed over how a mapping frame of $FF instructs the Animate_Sprite function to start over the animation from the beginning. In fact, the last few values within the range of a byte are all reserved as control codes for the animation functions, limiting the number of frames a set of sprite mappings can have.

The Animate_Sprite function in particular starts off by checking if the sign bit on the value is set, and if so, interprets the value as a control code rather than a mapping frame. As a result, even though there only exist a handful of valid control codes, most objects are limited to a maximum of 128 mapping frames.

Player objects, on the other hand, actually have their own animation functions, which apart from adding a few bells and whistles, only interpret a few select values as control codes, increasing the maximum number mapping frames to 252.

Here's a rundown of all the control codes and their effects:

  • $FF: Restarts the animation. This is accomplished by setting byte $23, the animation frame, back to 0.
  • $FE: Rewinds the animation by the given number of frames. This is accomplished by subtracting a number from byte $23. The next byte indicates the number of frames to subtract. 
  • $FD: Starts a new animation. This is accomplished by writing the new animation to byte $20. The next byte indicates which animation to start.

The remaining control codes are exclusive to non-player objects:


Note that if control code $FD is used to start an animation when the same animation is already playing, nothing special will happen, and the function will happily continue reading bytes as additional frames in the current animation. Because byte $20 still has the same value as byte $21, no animation change is detected.

This situation is one of the few where messing with the animation function's bookkeeping becomes mandatory: in order to externally force an animation change, a sentinel value such as $FF may be written to the object's previous animation byte at $21. $FF is not a valid animation, so it is impossible for $20 and $21 to be equal, ensuring an animation change is detected.

No comments:

Post a Comment