The Animation Class

From this we can define the requirements for an Animation class, which stores the data for a single animation, such as the walk animation in Figure 8-25:

An Animation holds a number of TextureRegions, which store where in the texture atlas each keyframe is located. The order of the TextureRegions is the same as that used for playing back the animation.

The Animation also stores the frame duration that has to pass before we switch to the next frame.

The Animation should provide us with a method to which we pass the time we've been in the state that the Animation represents (e.g., walking left), and that will return the appropriate TextureRegion. The method should take into consideration whether we want the Animation to loop or to stay at the last frame when the end is reached.

This last bullet point is important because it allows us to store a single Animation instance to be used by multiple objects in our world. An object just keeps track of its current state (e.g., whether it is walking, shooting, or jumping, and how long it has been in that state). When we render this object, we use the state to select the animation we want to play back, and the state time to get the correct TextureRegion from the Animation. Listing 8-19 shows the code of our new Animation class.

Listing 8-19. Animation.java, a Simple Animation Class package com.badlogic.androidgames.framework.gl;

public class Animation {

public static final int ANIMATION_LOOPING = 0; public static final int ANIMATION_NONLOOPING = 1;

final TextureRegion[] keyFrames; final float frameDuration;

public Animation(float frameDuration, TextureRegion ... keyFrames) { this.frameDuration = frameDuration; this.keyFrames = keyFrames;

public TextureRegion getKeyFrame(float stateTime, int mode) { int frameNumber = (int)(stateTime / frameDuration);

if(mode == ANIMATION_NONLOOPING) {

frameNumber = Math.min(keyFrames.length-1, frameNumber); } else {

frameNumber = frameNumber % keyFrames.length;

return keyFrames[frameNumber];

We first define two constants to be used with the getKeyFrame() method. The first one says the animation should be looping, and the other one says that is should stop at the last frame.

Next we define two members: an array holding the TextureRegions and a float storing the frame duration.

We pass the frame duration and the TextureRegions that hold the keyframes to the constructor, which simply stores them. We could make a defensive copy of the keyFrames array, but that would allocate a new object, which would make the garbage collector a little mad.

The interesting piece is the getKeyFrame() method. We pass in the time that the object has been in the state that the animation represents, as well as the mode, either Animation.ANIMATION_LOOPING or Animation.NON_LOOPING. We first calculate how many frames have already been played for the given state based on the stateTime. In case the animation shouldn't be looping, we simply clamp the frameNumber to the last element in the TextureRegion array. Otherwise, we take the modulus, which will automatically create the looping effect we desire (e.g., 4 % 3 = 1). All that's left is returning the proper TextureRegion.

0 0

Post a comment