Using sequences of images for animations

Up until now, all the animations we have created are based on changing attributes, such as the position, color value, and size, of still images. Therefore, our next enhancement is targeted toward the game objects that inhabit the game world of Canyon Bunny. We want to breathe life into the gold coin and bunny head game objects by creating several animations that are built from sequences of individual images. The resulting effect is very similar in comparison to an ordinary flip book where multiple images are perceived as a continuous animation when shown in rapid succession.

LibGDX provides a class called Animation that helps us define image sequences and also helps us to pick the right (key) frame from a sequence at a specific time which, for example, depends on the desired frame rate for playback. There is some clever mathematics and state-keeping involved for finding the right frame in an efficient way. Luckily, the Animation class saves us from having to go down that mathematical road and lets us just do animations the easy way with a variety of extra playback options.

Packing animations using TexturePacker

Before we look any further into the Animation class, let's first cover a great feature of LibGDX's TexturePacker that should be used when working with animations. Whenever TexturePacker builds a new texture atlas, it always scans the end of each image filename for an underscore followed by a number like waterfall_03.png. In this case, the number 03 is considered as the frame index of this animation, while the animation itself will be named and referred to as waterfall in the texture atlas.

Let's imagine that we have a five-frame animation called waterfall. So, according to the mentioned pattern for allowing animation frames to be recognized by TexturePacker, we would name our image files as follows:

  • waterfall_01.png
  • waterfall_02.png
  • waterfall_03.png
  • waterfall_04.png
  • waterfall_05.png

The following short code example further illustrates the line of action to build animations:

TextureAtlas atlas = assetManager.get("atlas.pack");
AtlasRegion firstFrame = atlas.findRegion("waterfall");
AtlasRegion thirdFrame = atlas.findRegion("waterfall", 3);
Array<AtlasRegion> allFrames = atlas.findRegions("waterfall");

Let's assume that the waterfall animation is now available in the texture atlas (atlas.pack). To retrieve any given image from a texture atlas, we already know that we can simply call the findRegion() method and pass in the original filename without its extension to reference it. The preceding code example shows that you can also do this with an animation to get the first frame, or you can pass a second argument to specify a concrete frame index like index number 3 to get the third frame. The next line uses the findRegions() method instead of findRegion(). Notice the plural s in the method's name. This method returns a whole array of frames associated with the supplied name which is stored in the allFrames variable for now.

The following lines of code show how new animations are built using the Animation class:

float fps = 1.0f / 15.0f; // Time between frames in seconds
Animation aniFirst, aniFirstThird, aniAll, aniAllPingpong;
aniFirst       = new Animation(fps, firstFrame);
aniFirstThird  = new Animation(fps, firstFrame, thirdFrame);
aniAll         = new Animation(fps, allFrames);
aniAllPingPong = new Animation(fps, allFrames, Animation.PlayMode.LOOP_PINGPONG);

The constructor of the class takes the time given in seconds that describes the time stepping or delay between the current and the next frame that is to be displayed. In this example, we use a frame rate of 15 frames per second. As the example code shows us further, we can pass in either an arbitrary number of AtlasRegion objects (our individual frames) or an array of those objects to define what frames should be used and in what particular order. Another feature of the Animation class is its play mode.

Choosing between animation play modes

There are six distinct play modes we can choose from. They are as follows:

  • NORMAL: This plays the animation once (first frame to last)
  • REVERSED: This plays the animation once (last frame to first)
  • LOOP: This plays the animation in a loop (first frame to last)
  • LOOP_REVERSED: This plays the animation in a loop (last frame to first)
  • LOOP_PINGPONG: This plays the animation in a loop (first frame, to last, to first)
  • LOOP_RANDOM: This plays the animation in a loop (random frames)

The NORMAL play mode is used as default if it is not explicitly set in the code.

Finally, the animations are now ready to be used and queried for their frames that should be currently displayed according to calculations. These calculations require one input value, which is the so-called state time, as shown in the following code. The state time is the elapsed time of an animation given in seconds. Usually, game objects keep track of their animation time, as we will see shortly:

TextureRegion region = aniAll.getKeyFrame(stateTime);

Assuming that the stateTime in the preceding code line yields a value of 0 seconds, the region variable will contain the first frame defined in the aniAll animation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.251.57