Handling Frame Based Animation

Monkey Forums/Monkey Programming/Handling Frame Based Animation

Raz(Posted 2012) [#1]
Does anyone have any thoughts on handling in game animations of characters?

To keep it simple let's say it's a character that can move in 4 directions and has 5 animation sets, Standing, Walking, Shooting, In Air and Getting Hurt.

Each of these animations has 4 frames that loop per direction and 4 directions (so 16 frames per animation).

I've just started working on this and already it's beginning to feel like a bit of a bodge job. The part that works out which animation should currently be playing doesn't seem very elegant ("Ok so if you're moving play the walking animation, unless you're shooting where it will play the shooting animation unless you are hurting, if so play the getting hurt animation"... unless of course you are off the ground.. if so play the in air animation")

I assume many of you have already come across this and come up with a nice solution :)

Ta!
-Chris


muddy_shoes(Posted 2012) [#2]
The usual thing would be to create a state machine for those states. So, the player is idling and from the idle state the fire button will move it to the shooting state or the left and right button will move it to the walking state and getting shot will move it to the hurt state. Each state then plays the corresponding animation.

It can all get more tricksy if you're doing animation blending or have entry and exit points for your animations, but for most 2D platformer sorts of things you just flip state and immediately change animation.


Shinkiro1(Posted 2012) [#3]
Instead of doing a state machine you could create a dedicated animation class/type.
Then you plug this animation class into your object class.

Type TFrameAnimation
  Field frames:TImage[]
  
  Method Update()
    'Do your updating here
  End Method
End Type

Type YourObject
  Field animation:TFrameAnimation

  Method ChangeAnimation (newAnim:TFrameAnimation)
    animation = newAnim
  End Method

  Method Update()
    If animation
      animation.Update()
    EndIf
  End Method
End Type


If one of your animations is completely different than your others you can extend TFrameAnimation, override it's Update Method and still can plug it into YourObject class.


Rex Rhino(Posted 2012) [#4]
Yep, in my object that represents the player (or whatever), I would just have a variable that represents the current state, and then do a case statement to determine which animation to use. Fortunately, with 4 frames per loop, you don't need to worry about animation blending or anything like that - just jump from your walking to your standing, etc.

Also, if you are doing a top-down style map, you could have the body, head, feet, etc., as separate graphics, and move them relative to a center pivot for animation. For each state, you have a 0.0 location of the body part (lets say the left foot is back and the right foot is forward), and a 1.0 location (lets say the left foot is forward and the right foot is back)... Then you tween in between the two states based on millisec value. The benefit of this method is you don't need to store multiple frames of animation, and it is always smooth, and when the state is changed you just tween the objects to their next position from where they are, making transitions smooth.


Jesse(Posted 2012) [#5]
the way I do it it's similar to what everybody being saying. I used a state state machine with a case select and an animation for each of the character animation conditions.
you can see it here in the SOB animation:
http://www.hexobot.com/html5/MonkeyGame.html

I don't know if it will help you but here is the source code:



Raz(Posted 2012) [#6]
Thanks for the replies everyone :)

I was messing with this yesterday evening and I think I almost have a system that doesn't feel like I am completely fudging everything together.

Each animation has a priority and an animation finished action (either loop, or change the animation). The animation class can be extended to make it conditional too, so the walking animation will continue to play on the condition that the player is moving, once this is not the case the animation can fall back to another specified one (in this case a standing animation).

The shooting animation is triggered when the player shoots and as it has a higher priority than walking and standing, it plays.

I had tried a Select Case statement but seeing as a lot of the conditions can overlap (e.g. you can move and shoot, or shoot standing still etc), it felt like I was losing control of things.

So each update of the player I have
Method Update:Void()
    animation.Change(ANI_STANDING)

    If isMoving = True
        animation.Change(ANI_WALKING)
    End

    If KeyHit(SHOOT_BUTTON)
        animation.Change(ANI_SHOOTING)
    End

    animation.Update()

End


Each animation instance contains details regarding location in tileset, frames, time per frames. The Change() method should really be AttemptChange() because it doesn't always occur because of priorities.

The above example doesn't show it, but the system lets me trigger animations from anywhere within the code regardless of the logical order. I have a weapon sub class for the player and I can use this to trigger the ANI_SHOOTING animation.

I'm not sure if this is just useful for me as it's very specific about how the frames are stored in the tileset, but if anyone is interested, I'd be happy to tidy it up a bit and post it in the code archive.


Jesse(Posted 2012) [#7]
sounds very interesting. I would really love to se how you did it. I am sure it will have some interesting concepts that will be useful to me and others. Even if I don't use it as is, I am sure will provide me with some ideas on how I can adopt it for future use.