XNA Tutorials, Samples and Thoughts
2D Skeletal Animations
What is your preferred way of doing animations in 2D?
Most of you will probably answer “spritesheets”, and you’d be right. Creating animations using spritesheets is quick, easy, there are helpful resources on the net and if you work with an external artist, he only needs to give you the individual frames of the animation (which also makes his life easy).
You would want to have a framerate of at least 12 for your animations, and you soon end up with something like this:
And with minimal effort, you can write code that loads this and displays it as an animation [SpriteSheetAnimation.zip]
All is well in the world, until you realize your game needs LOTS of animations and the memory consumption goes way up, together with the time required to load all the data. Also, to limit the size, you need to limit yourself to a low FPS for the animation (like 12), which also means the animation doesn’t look as smooth as you’d like. This is where skeletal animation comes in.
When using skeletal animation, the animation is composed of several bones which are connected to one another. Affecting a bone also affects all of its children. By composing different transformations on each bone, you obtain different poses for the skeleton.
Now, if you define keyframes with certain transformations for a point in time for each of the bones in the skeleton, you can interpolate between the keyframes to obtain a smooth transition and thus animate the skeleton.
In the attached code, I used a class named Transformation, which contains data about 2D transformations, like translation, rotation and scale. Then, a Keyframe is defined by a frame number and one such Transformation. A collection of Keyframes defines a KeyframeAnimation. Finally, a SkeletonAnimation is a collection of KeyframeAnimations, one for each bone in the skeleton.
Separately, I use a Skeleton, which keeps a list of Joints that define the hierarchy of bones in the skeleton. Each bone is then assigned a certain texture, like the ones below:
Each of the parts are individually animated relative to their parent bone, and thus the animation is obtained. In the sample, the animation is stored in two XML files that are loaded directly into a Skeleton (see machine_skeleton.xml ) and a SkeletonAnimation (see machine_animation.xml ) using the ContentPipeline at runtime. Here’s a video of the sample using skeleton animation:
As you can see, it runs much smoother than the initial frame-based animation. Also, looking at the resources used, the amount of texture data loaded into memory is significantly reduced (from 5.12 Mb to only 73Kb).
A word on how the XML file was generated. There are multiple options here.
- make a tool for editing animations, where you would set-up the positions of each frame and serialize it to disk using the IntermediateSerializer.
- let your artist create the animation in a software of is choice that can output the keyframes to XML, and then write a small program that converts that XML in the suitable format to be loaded by the Content Pipeline. For the animation above, I used a Flash animation created by a friend, exported the keyframes to ActionScript3 XML, and then converted that XML into the one you can see in the sample. (I won’t release that mini-tool however, since its code is a mess thrown together in about 1 hour).
A word of warning: while skeletal animation helps solve some problems with memory, loading times, smoothness, it is not a silver bullet. The amount of detail that can go into a normal sprite-sheet animation far surpasses what can be done with a skeletal animation. In skeletal animations you are limited to certain transformations on each ‘piece’ of the animation: translate, rotate, scale, flip. Meanwhile, frame-based animation allows the artist to add any kind of effect he likes.
I hope you enjoyed this sample. Feel free to leave any feedback and questions below.
To get the code, either download it directly (SkeletalAnimation.zip) or go to the sample’s page.
Until next time,
Happy coding!
| Print article | This entry was posted by Catalin Zima on June 14, 2011 at 11:27 pm, and is filed under 2D, sample, XNA. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |

about 8 months ago
Having gone down this route myself, I would recommend AGAINST IT. Check out how Maya was used to create Mika Mobile’s Zombieville game.
http://www.thecareergamer.com/braaaains-zombieville-usa-tech-review/
I would recommend using 3D even for 2D so you don’t need to code your own editor and the artists can use off the shelf tools for most of their work.
about 8 months ago
Keyframed animation is the best thing I’ve added into my game so far. As a one-man team, I would never have enough time to create a spritesheet of animations, and by using silhouette-style art ala Limbo/Patapon, you can really cheat on the animations as you’re only concerned with the outlines
about 8 months ago
Neat. I wrote a tool to create 2d skeletal animations, myself. (There’s also some code for loading them up into XNA games.) It’s been used in a few games so far.
http://demina.codeplex.com/
Also, there’s no reason you can’t mix spritesheet and skeletal animations. (Demina supports that, though you can’t start with premade spritesheets.)
about 8 months ago
Using Maya to create a 3D animation that you later import in your game is no different then one of my suggestions of using a tool that the artist is familiar with and exporting from that tool in a proper format.
) to compose animations and all sort of special effects. Then we have some scripts we run to convert the animation into a properly formatted XML file that we can load directly in our game.
In Chickens Can’t Fly, our artist uses AfterEffect or Flash (which I might say are ‘off the shelf’ tools
This means that artists can use his choice of tools, and we can use skeletal animation just fine without writing an editor.
about 8 months ago
Quite true. In our ‘production’ system, we combine spritesheets and skeletal animations when needed, so some animations are classic spritesheets, with lots of details and stuff that couldn’t be handled by skeletons, and whenever we can use skeletal animation, we do so.
about 8 months ago
Very nice. The game I’m making is using a similar approach. This also makes it easy to integrate scripting with the animations, playing sounds at certain keyframes etc. I’ve found that it’s a lot quicker, especially if you’re not a great artist, to do these kind of animations.
about 7 months ago
Catalin, nice sample. You wouldn’t care to share some of the “scripts we run to convert the [flash] animation into a properly formatted XML file”? This approach is definitely the way forward.
about 7 months ago
I just re-read the section where you said you wouldn’t release it. Personally I don’t mind messy code, at least it’s a place to start from
about 7 months ago
The script that converts the AfterEffects animations into skeletal animations was developed inside Evozon and is company property, so I can’t release that.
However, I’ll try to look into releasing the code I used for the Flash animations, which belongs to the prototype I developed at home. It’s mostly just XML conversion and is a rather manual process, but I’ll see what I can do.
about 7 months ago
Ok, I thought you’d be exporting all the animation data right from Flash, which I’m sure is possible. I think Super Meat Boys guys have an exporter which does sprite sheets AND animation data, which pretty awesome. Anyway, when you do release any code, it’s always much appreciated!
about 7 months ago
Thank you for this very interesting post. I have been looking for something like this for some time.
I have previously worked with flash and have some experience with keyframe animation. So, I downloaded the trial version of Flash CS5 and started to create a basic animation to test. I got that done but I have not figured out yet how to export keyframes to XML. Would you mind explaining how you did that?
about 4 months ago
I want nothing more but circles all around. I love the shape. I’m not quite good at 2D or animation in general; but darn I’m trying so hard. Argh! Any tips peeps? Gladly appreciate if you will.
about 4 months ago
Thanks for sharing this code – now time to sit down and get to working with it.
about 1 month ago
Hi Catalin,
I discovered a possible mistake in your file Transformation.cs, function public Vector2 TransformPoint(Vector2 point).
You have to scale the point bevore transforming it with the rotated matrix.
The code will then be like that:
Vector2 result = Vector2.Transform(point * Scale, Matrix.CreateRotationZ(Rotation));
// result *= Scale; // is wrong here!
result += Position;
return result;
Kind regards from Germany,
Tim