24 min read

In this article, created by Siddharth Shekhar, the author of Learning Cocos2d-x Game Development, we will learn different tools that can be used to animate the character. Then, using these animations, we will create a simple state machine that will automatically check whether the hero is falling or is being boosted up into the air, and depending on the state, the character will be animated accordingly.

We will cover the following in this article:

  • Animation basics
  • TexturePacker
  • Creating spritesheet for the player
  • Creating and coding the enemy animation
  • Creating the skeletal animation
  • Coding the player walk cycle

(For more resources related to this topic, see here.)

Animation basics

First of all, let’s understand what animation is. An animation is made up of different images that are played in a certain order and at a certain speed, for example, movies that run images at 30 fps or 24 fps, depending on which format it is in, NTSC or PAL. When you pause a movie, you are actually seeing an individual image of that movie, and if you play the movie in slow motion, you will see the frames or images that make up to create the full movie.

In games while making animations, we will do the same thing: adding frames and running them at a certain speed. We will control the images to play in a particular sequence and interval by code.

For an animation to be “smooth”, you should have at least 24 images or frames being played in a second, which is known as frames per second (FPS). Each of the images in the animation is called a frame.

Let’s take the example of a simple walk cycle. Each walk cycle should be of 24 frames. You might say that it is a lot of work, and for sure it is, but the good news is that these 24 frames can be broken down into keyframes, which are important images that give the illusion of the character walking. The more frames you add between these keyframes, the smoother the animation will be. The keyframes for a walk cycle are Contact, Down, Pass, and Up positions.

For mobile games, as we would like to get away with as minimal work as possible, instead of having all the 24 frames, some games use just the 4 keyframes to create a walk animation and then speed up the animation so that player is not able to see the missing frames. So overall, if you are making a walk cycle for your character, you will create eight images or four frames for each side. For a stylized walk cycle, you can even get away with a lesser number of frames.

For the animation in the game, we will create images that we will cycle through to create two sets of animation: an idle animation, which will be played when the player is moving down, and a boost animation, which will get played when the player is boosted up into the air.

Creating animation in games is done using two methods. The most popular form of animation is called spritesheet animation and the other is called skeletal animation.

Spritesheet animation

Spritesheet animation is when you keep all the frames of the animation in a single file accompanied by a data file that will have the name and location of each of the frames. This is very similar to the BitmapFont.

The following is the spritesheet we will be using in the game. For the boost and idle animations, each of the frames for the corresponding animation will be stored in an array and made to loop at a particular predefined speed.

The top four images are the frames for the boost animation. Whenever the player taps on the screen, the animation will cycle through these four images appearing as if the player is boosted up because of the jetpack.

The bottom four images are for the idle animation when the player is dropping down due to gravity. In this animation, the character will look as if she is blinking and the flames from the jetpack are reduced and made to look as if they are swaying in the wind.

Skeletal animation

Skeletal animation is relatively new and is used in games such as Rayman Origins that have loads and loads of animations. This is a more powerful way of making animations for 2D games as it gives a lot of flexibility to the developer to create animations that are fast to produce and test.

In the case of spritesheet animations, if you had to change a single frame of the animation, the whole spritesheet would have to be recreated causing delay; imagine having to rework 3000 frames of animations in your game.

If each frame was hand painted, it would take a lot of time to produce the individual images causing delay in production time, not to mention the effort and time in redrawing images.

The other problem is device memory. If you are making a game for the PC, it would be fine, but in the case of mobiles where memory is limited, spritesheet animation is not a viable option unless cuts are made to the design of the game.

So, how does skeletal animation work? In the case of skeletal animation, each item to be animated is stored in a separate spritesheet along with the data file for the locations of the individual images for each body part and object to be animated, and another data file is generated that positions and rotates the individual items for each of the frames of the animation. To make this clearer, look at the spritesheet for the same character created with skeletal animation:

Here, each part of the body and object to be animated is a separate image, unlike the method used in spritesheet animation where, for each frame of animation, the whole character is redrawn.

TexturePacker

To create a spritesheet animation, you will have to initially create individual frames in Photoshop, Illustrator, GIMP or any other image editing software. I have already made it and have each of the images for the individual frames ready.

Next, you will have to use a software to create spritesheets from images. TexturePacker is a very popular software that is used by industry professionals to create spritesheets. You can download it from https://www.codeandweb.com/. These are the same guys who made PhysicsEditor, which we used to make shapes for Box2D.

You can use the trial version of this software. While downloading, choose the version that is compatible with your operating system. Fortunately, TexturePacker is available for all the major operating systems, including Linux. Refer to the following screenshot to check out the steps to use TexturePacker:

Once you have downloaded TexturePacker, you have three options: you can click to try the full version for a week, or you can purchase the license, or click on the essential version to use in the trial version. In the trial version, some of the professional features are disabled, so I recommend trying the professional features for a week. Once you click the option, you should see the following interface:

Texture packer has three panels; let’s start from the right. The right-hand side panel will display the names of all the images that you select to create the spritesheet. The center panel is a preview window that shows how the images are packed. The left-hand side panel gives you options to store the packed texture and data file to be published to and decide the maximum size of the packed image. The Layout section gives a lot of flexibility to set up the individual images in TexturePacker, and then you have the advanced section.

Let’s look at some of the key items on the panel on the left.

The display section

The display section consists of the following options:

  • Data Format: As we saw earlier, each exported file creates a spritesheet that has a collection of images and a data file that keeps track of the positions on the spritesheet. The data format usually changes depending upon the framework or engine. In TexturePacker, you can select the framework that you are using to develop the game, and TexturePacker will create a data file format that is compatible with the framework. If you look at the drop-down menu, you can see a lot of popular frameworks and engines in the list such as 2DToolkit, OGRE, Cocos2d, Corona SDK, LibGDX, Moai, Sparrow/Starling, SpriteKit, and Unity. You can also create a regular JSON file too if you wish.

    Java Script Object Notification (JSON) is similar to an XML file that is used to store and retrieve data. It is a collection of names and value pairs used for data interchanging.

  • Data file: This is the location where you want the exported file to be placed.
  • Texture format: Usually, this is set to .png, but you can select the one that is most convenient. Apart from PNG, you also have PVR, which is used so that people cannot view the image readily and also provides image compression.
  • Png OPT file: This is used to set the quality of PNG images.
  • Image format: This sets the RGB format to be used; usually, you would want this to be set at the default value.
  • AutoSD: If you are going to create images for different resolutions, this option allows you to create resources depending on the different resolutions you are developing the game for, without the need for going into the graphics software, shrinking the images and packing them again for all the resolutions.
  • Content protection: This protects the image and data file with an encryption key so that people can’t steal spritesheets from the game file.

The Geometry section

The Geometry section consists of the following options:

  • Max size: You can specify the maximum width and height of the spritesheet depending upon the framework. Usually, all frameworks allow up to 4092 x 4092, but it mostly depends on the device.
  • Fixed size: Apparently, if you want a fixed size, you will go with this option.
  • Size constraint: Some frameworks prefer the spritesheets to be in the power of 2 (POT), for example, 32×32, 64×64, 256×256, and so on. If this is the case, you need to select the size accordingly. For Cocos2d, you can choose any size.
  • Scale: This is used to scale up or scale down the image.

The Layout section

The Layout section consists of the following options:

  • Algorithm: This is the algorithm that will be used to make sure that the images you select to create the spritesheet are packed in the most efficient way. If you are using the pro version, choose MaxRects, but if you are using the essential version, you will have to choose Basic.
  • Border Padding / Shape Padding: Border padding packs the gap between the border of the spritesheet and the image that it is surrounding. Shape padding is the padding between the individual images of the spritesheets. If you find that the images are getting overlapped while playing the animation in the game, you might want to increase the values to avoid overlapping.
  • Trim: This removes the extra alpha that is surrounding the image, which would unnecessarily increase the image size of the spritesheet.

Advanced features

The following are some miscellaneous options in TexturePacker:

  • Texture path: This appends the path of the texture file at the beginning of the texture name
  • Clean transparent pixels: This sets the transparent pixels color to #000
  • Trim sprite names: This will remove the extension from the names of the sprites (.png and .jpg), so while calling for the name of the frame, you will not have to use extensions

Creating a spritesheet for the player

Now that we understand the different items in the TextureSettings panel of TexturePacker, let’s create our spritesheet for the player animation from individual frames provided in the Resources folder.

  1. Open up the folder in the system and select all the images for the player that contains the idle and boost frames. There will be four images for each of the animation. Select all eight images and click-and-drag all the images to the Sprites panel, which is the right-most panel of TexturePacker.
  2. Once you have all the images on the Sprites panel, the preview panel at the center will show a preview of the spritesheet that will be created:
  3. Now on the TextureSettings panel, for the Data format option, select cocos2d. Then, in the Data file option, click on the folder icon on the right and select the location where you would like to place the data file and give the name as player_anim. Once selected, you will see that the Texture file location also auto populates with the same location. The data file will have a format of .plist and the texture file will have an extension of .png.

    The .plist format creates data in a markup language similar to XML. Although it is more common on Mac, you can use this data type independent of the platform you use while developing the game using Cocos2d-x.

  4. Keep the rest of the settings the same.
  5. Save the file by clicking on the save icon on the top to a location where the data and spritesheet files are saved. This way, you can access them easily the next time if you want to make the same modifications to the spritesheet.
  6. Now, click on the Publish button and you will see two files, player_anim.plist and player_anim.png, in the location you specified in the Data file and Location file options.
  7. Copy and paste these two files in the Resources folder of the project so that we can use these files to create the player states.

Creating and coding enemy animation

Now, let’s create a similar spritesheet and data file for the enemy also. All the required files for the enemy frames are provided in the Resources folder.

So, once you create the spritesheet for the enemy, it should look something like the following screenshot. Don’t worry if the images are shown in the wrong sequence, just make sure that the files are numbered correctly from 1 to 4 and it is in the sequence the animations needs to be played in.

Now, place the enemy_anim.png spritesheet and data file in the Resources folder in the directory and add the following lines of code in the Enemy.cpp file to animate the enemy:

  //enemy animation      
CCSpriteBatchNode* spritebatch = CCSpriteBatchNode::create("enemy_anim.png");
  
CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();
   cache->addSpriteFramesWithFile("enemy_anim.plist");
  
   this->createWithSpriteFrameName("enemy_idle_1.png");
   this->addChild(spritebatch);  
      
   //idle animation
   CCArray* animFrames = CCArray::createWithCapacity(4);  
   char str1[100] = {0};
   for(int i = 1; i <= 4; i++)
   {
       sprintf(str1, "enemy_idle_%d.png", i);
       CCSpriteFrame* frame = cache->spriteFrameByName( str1 );
       animFrames->addObject(frame);
   }
      
   CCAnimation* idleanimation = CCAnimation::createWithSpriteFrames(animFrames, 0.25f);
   this->runAction (CCRepeatForever::create(CCAnimate::create(idleanimation))) ;

This is very similar to the code for the player. The only difference is that for the enemy, instead of calling the function on the hero, we call it to the same class. So, now if you build and run the game, you should see the enemy being animated.

The following is the screenshot from the updated code. You can now see the flames from the booster engine of the enemy. Sadly, he doesn’t have a boost animation but his feet swing in the air.

Now that we have mastered the spritesheet animation technique, let’s see how to create a simple animation using the skeletal animation technique.

Creating the skeletal animation

Using this technique, we will create a very simple player walk cycle. For this, there is a software called Spine by Esoteric Software, which is a very widely used professional software to create skeletal animations for 2D games. The software can be downloaded from the company’s website at http://esotericsoftware.com/spine-purchase:

There are three versions of the software available: the trial, essential, and professional versions. Although majority of the features of the professional version are available in the essential version, it doesn’t have ghosting, meshes, free-form deformation, skinning, and IK pinning, which is in beta stage. The inclusion of these features does speed up the animation process and certainly takes out a lot of manual work for the animator or illustrator.

To learn more about these features, visit the website and hover the mouse over these features to have a better understanding of what they do.

You can follow along by downloading the trial version, which can be done by clicking the Download trial link on the website.

Spine is available for all platforms including Windows, Mac, and Linux. So download it for the OS of your choice. On Mac, after downloading and running the software, it will ask to install X11, or you can download and install it from http://xquartz.macosforge.org/landing/. After downloading and installing the plugin, you can open Spine. Once the software is up and running, you should see the following window:

Now, create a new project by clicking on the spine icon on the top left. As we can see in the screenshot, we are now in the SETUP mode where we set up the character.

On the Tree panel on the right-hand side, in the Hierarchy pane, select the Images folder. After selecting the folder, you will be able to select the path where the individual files are located for the player. Navigate to the player_skeletal_anim folder where all the images are present. Once selected, you will see the panel populate with the images that are present in the folder, namely the following:

  • bookGame_player_Lleg
  • bookGame_player_Rleg
  • bookGame_player_bazooka
  • bookGame_player_body
  • bookGame_player_hand
  • bookGame_player_head

Now drag-and-drop all the files from the Images folder onto the scene. Don’t worry if the images are not in the right order. In the Draw Order dropdown in the Hierarchy panel, you can move around the different items by drag-and-drop to make them draw in the order that you want them to be displayed. Once reordered, move the individual images on the screen to the appropriate positions:

You can move around the images by clicking on the translate button on the bottom of the screen. If you hover over the buttons, you can see the names of the buttons.

We will now start creating the bones that we will use to animate the character.

In the panel on the bottom of the Tools section, click on the Create button. You should now see the cursor change to the bone creation icon. Before you create a bone, you have to always select the bone that will be the parent. In this case, we select the root bone that is in the center of the character.

Click on it and drag downwards and hold the Shift key at the same time. Click-and-drag downwards up to the end of the blue dress of the character; make sure that the blue dress is highlighted. Now release the mouse button. The end point of this bone will be used as the hip joint from where the leg bones will be created for the character.

Now select the end of the newly created bone, which you made in the last step, and click-and-drag downwards again holding Shift at the same time to make a bone that goes all the way to the end of the leg. With the leg still getting highlighted, release the mouse button.

To create the bone for the other leg, create a new bone again starting from end of the first bone and the hip joint, and while the other leg is selected, release the mouse button to create a bone for the leg.

Now, we will create a bone for the hand. Select the root node, the node in the middle of the character while holding Shift again, and draw a bone to the hand while the hand is highlighted.

Create a bone for the head by again selecting the root node selected earlier. Draw a bone from the root node to the head while holding Shift and release the mouse button once you are near the ear of the character and the head is highlighted.

You will notice that we never created a bone for the bazooka. For the bazooka, we will make the hand as the parent bone so that when the hand gets rotated, the bazooka also rotates along. Click on the bazooka node on the Hierarchy panel (not the image) and drag it to the hand node in the skeleton list.

You can rotate each of the bones to check whether it is rotating properly. If not, you can move either the bones or images around by locking either one of them in its place so that you can move or rotate the other freely by clicking either the bones or the images button in the compensate button at the bottom of the screen.

The following is the screenshot that shows my setup. You can use it to follow and create the bones to get a more satisfying animation.

To animate the character, click on the SETUP button on the top and the layout will change to ANIMATE. You will see that a new timeline has appeared at the bottom. Click on the Animations tab in Hierarchy and rename the animation name from animation to runCycle by double-clicking on it.

We will use the timeline to animate the character. Click on the Dopesheet icon at the bottom. This will show all the keyframes that we have made for the animation. As we have not created any, the dopesheet is empty.

To create our first keyframe, we will click on the legs and rotate both the bones so that it reflects the contact pose of the walk cycle. Now to set a keyframe, click on the orange-colored key icon next to Rotate in the Transform panel at the bottom of the screen. Click on the translate key, as we will be changing the translation as well later. Once you click on it, the dopesheet will show the bones that you just rotated and also show what changes you made to the bone. Here, we rotated the bone, so you will see Rotation under the bones, and as we clicked on the translate key, it will show the Translate also.

Now, frame 24 is the same as frame 0. So, to create the keyframe at frame 24, drag the timeline scrubber to frame 24 and click on the rotate and translate keys again.

To set the keyframe at the middle where the contact pose happens but with opposite legs, rotate the legs to where the opposite leg was and select the keys to create a keyframe.

For frames 6 and 18, we will keep the walk cycle very simple, so just raise the character above by selecting the root node, move it up in the y direction and click the orange key next to the translate button in the Transform panel at the bottom. Remember that you have to click it once in frame 6 and then move the timeline scrubber to frame 18, move the character up again, and click on the key again to create keyframes for both frames 6 and 18.

Now the dopesheet should look as follow:

Now to play the animation in a loop, click on the Repeat Animation button to the right of the Play button and then on the Play button.

You will see the simple walk animation we created for the character.

Next, we will export the data required to create the animation in Cocos2d-x.

First, we will export the data for the animation. Click on the Spine button on top and select Export. The following window should pop up. Select JSON and choose the directory in which you would want to save the file to and click on Export:

That is not all; we have to create a spritesheet and data file just as we created one in texture packer. There is an inbuilt tool in Spine to create a packed spritesheet.

Again, click on the Spine icon and this time select Texture Packer. Here, in the input directory, select the Images folder from where we imported all the images initially. For the output directory, select the location to where the PNG and data files should be saved to.

If you click on the settings button, you will see that it looks very similar to what we saw in TexturePacker. Keep the default values as they are.

Click on Pack and give the name as player. This will create the .png and .atlas files, which are the spritesheet and data file, respectively:

You have three files instead of the two in TexturePacker. There are two data files and an image file. While exporting the JSON file, if you didn’t give it a name, you can rename the file manually to player.json just for consistency.

Drag the player.atlas, player.json, and player.png files into the project folder.

Finally, we come to the fun part where we actually use the data files to animate the character.

For testing, we will add the animations to the HelloWorldScene.cpp file and check the result. Later, when we add the main menu, we will move it there so that it shows as soon as the game is launched.

Coding the player walk cycle

If you want to test the animations in the current project itself, add the following to the HelloWorldScene.h file first:

#include <spine/spine-cocos2dx.h>

Include the spine header file and create a variable named skeletonNode of the CCSkeletalAnimation type:

extension::CCSkeletonAnimation* skeletonNode;

Next, we initialize the skeletonNode variable in the HelloWorldScene.cpp file:

   skeletonNode = extension::CCSkeletonAnimation::createWithFile("player.json", "player.atlas", 1.0f);
   skeletonNode->addAnimation("runCycle",true,0,0);
   skeletonNode->setPosition(ccp(visibleSize.width/2 , skeletonNode->getContentSize().height/2));
   addChild(skeletonNode);

Here, we give the two data files into the createWithFile() function of CCSkeletonAnimation. Then, we initiate it with addAnimation and give it the animation name we gave when we created the animation in Spine, which is runCycle. We next set the position of the skeletonNode; we set it right above the bottom of the screen. Next, we add the skeletonNode to the display list.

Now, if you build and run the project, you will see the player getting animated forever in a loop at the bottom of the screen:

On the left, we have the animation we created using TexturePacker from CodeAndWeb, and in the middle, we have the animation that was created using Spine from Esoteric Software.

Both techniques have their set of advantages, and it also depends upon the type and scale of the game that you are making. Depending on this, you can choose the tool that is more tuned to your needs. If you have a smaller number of animations in your game and if you have good artists, you could use regular spritesheet animations. If you have a lot of animations or don’t have good animators in your team, Spine makes the animation process a lot less cumbersome.

Either way, both tools in professional hands can create very good animations that will give life to the characters in the game and therefore give a lot of character to the game itself.

Summary

This article took a very brief look at animations and how to create an animated character in the game using the two of the most popular animation techniques used in games. We also looked at FSM and at how we can create a simple state machine between two states and make the animation change according to the state of the player at that moment.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here