Jump to content
  • entries
    7
  • comments
    0
  • views
    2,551

Animation engine


mksmith

380 views

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*8 )
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!

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...