Wednesday, August 2, 2017

The global animation system, part 1

Along with standardized functions for drawing and deleting sprites, Sonic 3 also includes functions that automate sprite animation. Most objects just call the Animate_Sprite function, which takes in an animation script via the a1 register.
loc_2D0F8:
    lea     (Ani_Starpost).l,a1
    jsr     (Animate_Sprite).l
    jmp     (Sprite_OnScreen_Test).l
Animation scripts, much like sprite mappings, are lists of word-sized pointers to the actual animation definitions. These are indexed through byte $20 in an object's SST. Like sprite mappings, byte $20 is multiplied by two before being used as an index to the pointer list, allowing for a maximum of 256 animations per script.

The animation definition format itself is deceptively simple. The first byte is the number of frames to wait between each mapping frame, and the remaining bytes are the actual mapping frames to display.
byte_12B8D: dc.b    7, $A4, $A5, $A6, $FF
As an example, take byte_12B8D, which is animation $C in Sonic's animation script. When $C is written to byte $20 in Sonic's SST, his mapping frame in byte $22 changes to $A4, the first frame in the animation. Then, the animation does nothing for 7 frames, after which it changes $22 to $A5, the next frame in the animation. It waits again, changes $22 to $A6, and waits one last time. The $FF byte at the end then instructs the animation to start over from the beginning.

The result is that mapping frame $A4 will be displayed for 8 frames, then $A5, and then $A6, in a continuous loop.


This format is good for animations which play back at a constant speed, but is inconvenient when some frames need to be displayed longer than others. For instance, consider byte_12B20, which is Sonic's standing animation:
byte_12B20: dc.b    5, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA
            dc.b  $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA
            dc.b  $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA, $BA
            dc.b  $BA, $BA, $BA, $BB, $BC, $BC, $BD, $BD, $BE, $BE, $BD, $BD, $BE, $BE, $BD, $BD
            dc.b  $BE, $BE, $BD, $BD, $BE, $BE, $BD, $BD, $BE, $BE, $BD, $BD, $BE, $BE, $BD, $BD
            dc.b  $BE, $BE, $BD, $BD, $BE, $BE, $AD, $AD, $AD, $AD, $AD, $AD, $AE, $AE, $AE, $AE
            dc.b  $AE, $AE, $AF, $D9, $D9, $D9, $D9, $D9, $D9, $AF, $AF, $FE, $35
Half of this animation alone points to mapping frame $BA, which is the main standing sprite. The foot-tapping sprites at $BD and $BE, which are displayed alternately for 12 frames each, take up most of the remaining space, but the overall speed must cater to the lowest common denominator: the blinking sprite at $BB, which is only displayed for 6 frames.

No comments:

Post a Comment