RSS Bot #1 Posted December 29, 2018 As discussed in the previous blog post, i am interested in a reasonably reusable animation engine which allows me to call a SetAnimation function to initialise a new animation then use generic UpdateAnimation and DrawAnimation functions to process it regardless of what i need animating. I need to set the total frames, the speed of the animation (by screen update generally), the frame to display and any positional (x and y) change. When starting this game I followed a few example games across the forum for inspiration which generally make use of the gosub ... to set the specific frame to the sprite required with a number of lookup data tables. The one benefit of this game is the animation will process and finish before the next check is required which does simplify everything just a bit - I don't need (thankfully) to make changes during the animation (might make a nice engine for something like Lode Runner maybe). As I want to eventually make this a 2 player game I want to reuse the animation frames when required but I didn't want to just duplicate it all. As noted in the previous blog I found this forum post discussing how to make this a little more dynamic (but due to pointers it still carries a bit of duplication per sprite). So armed with this I setup the following: dim player0AnimationId = k dim player0AnimationFrame = m dim player0AnimationSpeed = n dim player0IsAnimating = o const ANIMATION_STATIONARY = 0 const ANIMATION_FALL = 1 const ANIMATION_HANG = 2 const ANIMATION_MOVE = 3 const ANIMATION_CHANGE_DIRECTION = 4 const ANIMATION_JUMP_UP = 5 const ANIMATION_CLIMB_UP = 6 const ANIMATION_CLIMB_DOWN = 7 const ANIMATION_JUMP_SMALL = 8 const ANIMATION_JUMP_LARGE = 9 function SetPlayer0Animation rem temp1=AnimationId player0AnimationId = temp1 player0IsAnimating = 1 player0AnimationFrame = 0 player0AnimationSpeed = 0 return function UpdatePlayer0Animation rem validate if !player0IsAnimating then return rem prepare (got offset) ftemp1 = PL_ANIMATION_OFFSET[player0AnimationId] rem update position? (only on 0) if player0AnimationSpeed > 0 then goto _SKIP_UPDATEPLAYER0ANIMATION_MOVE rem read x and y to offset rem data is TotalFrames,TotalSpeed(+2),Frame(+0),X(+1),Y(+2) rem update x fresult = ftemp1 + 2 + (player0AnimationFrame * 3) + 1 ftemp2 = PL_ANIMATION[fresult] if _Bit2_Player0_Dir_Left{2} then player0x = player0x - ftemp2 else player0x = player0x + ftemp2 rem update y fresult = fresult + 1 ftemp2 = PL_ANIMATION[fresult] player0y = player0y + ftemp2 _SKIP_UPDATEPLAYER0ANIMATION_MOVE rem increment speed player0AnimationSpeed = player0AnimationSpeed + 1 ;fresult = ftemp1 + 1 : if player0AnimationSpeed < 50 then goto _SKIP_UPDATEPLAYER0ANIMATION_FRAME fresult = ftemp1 + 1 : if player0AnimationSpeed < PL_ANIMATION[fresult] then goto _SKIP_UPDATEPLAYER0ANIMATION_FRAME player0AnimationSpeed = 0 rem increment frames player0AnimationFrame = player0AnimationFrame + 1 fresult = ftemp1 : if player0AnimationFrame < PL_ANIMATION[fresult] then goto _SKIP_UPDATEPLAYER0ANIMATION_FRAME rem complete player0IsAnimating = 0 : player0AnimationFrame = 0 : player0AnimationSpeed = 0 ... _SKIP_UPDATEPLAYER0ANIMATION_FRAME return function DrawPlayer0Animation rem prepare ftemp1 = PL_ANIMATION_OFFSET[player0AnimationId] fresult = ftemp1 + 2 + (player0AnimationFrame*3) + 0 : ftemp2 = PL_ANIMATION[fresult] rem get frame pointer asm LDX #<PL_ANIMATION_FRAMES STX ftemp5 end rem get frame player0pointerlo = ftemp5+(ftemp2* asm LDA #((>PL_ANIMATION_FRAMES) & $0f) | (((>PL_ANIMATION_FRAMES) / 2) & $70) STA player0pointerhi end return I then configured the data as below. The offset gives me the location in the PL_ANIMATION table for the active animation. From there I can look up the Total Frames and Speed, then for the current animation frame I can grab the frame to display and the x and y offset for the frame. rem ANIMATION rem 0-0 Stationary rem 1-5 Fall rem 2-31 Hang rem 3-36 Move rem 4-62 Change Direction rem 5-79 Jump (up) rem 6-87 Climb (up) rem 7-113 Climb (down) rem 8-139 Jump (small) rem 9-153 Jump (large) data PL_ANIMATION_OFFSET 0, 5, 31, 36, 62, 79, 87, 113, 139, 153 end data PL_ANIMATION 1,1, 0,0,0, 8,2, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,2, 2,0,0, 8,1, 0,1,0, 3,1,0, 4,1,-1, 5,1,0, 6,1,0, 7,1,0, 8,1,1, 9,1,0, 5,2, 10,0,0, 11,0,0, 12,0,0, 13,0,0, 14,0,0, 2,3, 15,0,0, 16,0,0, 8,3, 17,1,0, 18,0,-1, 19,1,-1, 20,2,0, 21,1,-2, 22,1,-2, 22,1,-1, 22,1,-1, 8,3, 22,-1,1, 22,-1,1, 22,-1,2, 21,-1,2, 20,-2,0, 19,-1,1, 18,0,1, 17,-1,0, 4,2, 23,0,0, 24,0,0, 25,0,0, 26,0,0, 8,2, 23,1,-1, 23,1,0, 24,1,0, 24,1,0, 25,1,0, 25,1,1, 26,1,0, 2,1,0 end data PL_ANIMATION_FRAMES %00011000 %00000100 %00011000 %00111100 %01011010 %00011000 %00101000 %00100100 %01000010 %01011010 %00100100 %00011000 %00011000 %00111000 %00101110 %00100000 %10000000 %10110000 %01000000 %01110000 %01101000 %01101000 %10100000 %10100000 ... end So i've got some further ideas about how this could work for a 2 player game (or multiple sprites such as enemies) using the same code by storing/restoring the state of the active object via some additional vars or DPC+ ram. If anyone has any suggestions to tiding up this further I'd be grateful - it has saved me about 700 bytes so far. I do find I'm needing to use a lot of temp variable declarations particularly around calculations. I guess I can't be too hard - being able to do this quickly in basic is pretty cool! http://atariage.com/forums/blog/751/entry-15381-animation-engine/ Share this post Link to post Share on other sites