Animation made easy in MonoGame with TexturePacker

Thanks to Randolph Burt for writing this tutorial!

TexturePacker Now Supports MonoGame!

By now I’m sure that you’re well aware of how TexturePacker can make in-game animation easier than ever. Well, we’ve now added the option to export from TexturePacker directly into MonoGame!

Here’s a look at an example of using TexturePacker to animate a MonoGame project:

In this article we will go through, step by step, how to produce the above video, and we’ll also give you a link to the source code.

TexturePacker

TexturePacker allows you to easily create sprite sheets and texture atlases, greatly simplifying the process of in-game animation. Here’s how it works – you take your individual animation frames (of characters, objects, etc.), and drag and drop them into TexturePacker. Then TexturePacker combines them into sprite sheets, which you can then load into your game. Using sprite sheets rather than individual images is a much more efficient process, making development quicker and easier for you! Here’s a video to explain how it all works:

TexturePacker has always been quite versatile, and compatible with numerous formats. However, we’ve now added the ability to save your sprite sheets and data files in a format compatible with MonoGame, as well as the source code to properly manage and use these files in your MonoGame app.

Here’s how to do it:

Start by downloading and installing TexturePacker from here. When you open it, you’ll see:

TexturePacker: new project

Choose MonoGame and then click on Create project.

TexturePacker: create project

Before continuing, make sure that all of the images you plan to import are in a logical folder structure (folder names based on animation type is recommended). Once your images are properly organized, drag and drop the parent folder into TexturePacker. The images that we’re using for this demonstration can be found here on GitHub.

TexturePacker will automatically group images together, as seen below:

TexturePacker: CapGuy Demo

Now that your images are in TexturePacker, you may need to alter some settings – this depends on your individual requirements and how you intend to use these images. We’ll explain all of the settings used for this tutorial, but complete documentation can be found here.

TexturePacker: Settings

Scaling Variants

A little bit later in this tutorial we’ll go through how to create an iOS app with MonoGame, using Xamarin Studio. If you’ve done development for iOS before, then you’re familiar with having to create two sets of graphics files – a normal set for standard resolution, and a high-resolution set for Retina displays. The operating system determines which set to use at run-time by the @2x appended to the high-resolution set.


When using MonoGame on an iOS device, it works the same way – Retina devices will load the @2x graphics automatically, while non-Retina devices will use the standard versions.

However, TexturePacker has a Scaling Variants feature that eliminates the need to create two separate sets of graphics. With this automated process, you can produce both Retina and non-Retina versions of your graphics without having to do all your work twice!

Let’s try it out! Start by clicking on the Scaling Variants gear, and the following screen will appear:

TexturePacker: scaling variants empty

In the Presets box, select generic @2x and then click Apply. The Scaling variants are automatically filled in as seen below:

TexturePacker: scaling variants populated

By entering this information into these fields, we are telling TexturePacker that we want two versions of the sprite sheet. Scale: 1 refers to the high-definition Retina version, and the Scale: 0.5 is the standard-definition non-Retina version. Variant name: @2x simply indicates that @2x will be appended onto the variant version’s filename.

Once you’ve finished entering the information, click Close.

If your app is intended for a specific device that is only available in either Retina or non-Retina (but not both) then there is no need for you to use the Scaling Variants feature.

Trim Mode

In TexturePacker’s Sprites section, look for Trim mode.

TexturePacker: settings trim mode

This should be set to Trim by default. This option crops all empty space surrounding your sprites, reducing the sprite sheet’s size. If you’d prefer not to use this option, Trim mode can be set to None.

The TexturePacker MonoGame Loader code will do all the trimming at runtime.

Pivot Points

Pivot points have two functions:

Export Files

Now let’s examine the files that are created when TexturePacker converts our images into sprite sheets.

TexturePacker: settings export files

You will initially see a Settings screen with mostly empty fields.

TexturePacker: settings export files populated

The {v} seen in both the Data file and Texture file fields above represents variant file names for the scaled variants. When the sprite sheet is exported, the {v} will be replaced with the variant name – in this case it will be replaced by @2x for the Retina display version, and will simply be removed for the non-Retina display version.

The Data file is a text file which contains information about each sprite in the sheet. This includes:

The Class file contains a C# class consisting of constants that are used to refer to each frame in the series. A little later we’ll go into more detail on this, but basically, in MonoGame each frame must be referenced by a string name. These must be exact, as any typo would cause a runtime error. However, with the use of const strings, errors become evident as compile time errors, allowing us to discover and correct these errors much earlier in the process.

/*
 * Class auto generated by TexturePacker
 * 
 * Contains references to each image within the sprite sheet.
 *
 * http://www.codeandweb.com/texturepacker
 * $TexturePacker:SmartUpdate:2044216056b85e7707659a24b50ece03...
 *
 */
namespace TexturePackerMonoGameDefinitions
{
    public class CapGuyDemo
    {
        public const string Background = "Background";
        public const string Capguy_turn_0001 = "capguy/turn/0001";
        public const string Capguy_turn_0002 = "capguy/turn/0002";
        public const string Capguy_turn_0003 = "capguy/turn/0003";
        public const string Capguy_turn_0004 = "capguy/turn/0004";
        public const string Capguy_turn_0005 = "capguy/turn/0005";
        public const string Capguy_turn_0006 = "capguy/turn/0006";

The Texture file is the file that actually contains the sprite sheet. Notice that this field also has a {v} in it. Therefore, because the name of the file listed here is CapGuyDemo{v}.png, when exported, this will produce two variants: a non-Retina version called CapGuyDemo.png and a Retina version called CapGuyDemo@2x.png.

At this point you may want to consider the location of these files. The Data file and Texture file both need to be in the Content folder in order for the app to run properly, so to save yourself the trouble to saving them in some other location and then copying them to Content, you could just save them there now. Additionally, the Class file will need to be within the app’s source tree, so you might as well save it in that location now, too.

As mentioned, there are other options in addition to the ones explained here, but because these are the only ones you need for this tutorial, we’ll move on now. However, feel free to explore other options on your own here.

At this point, you should save your work in TexturePacker and click Publish. This will export your sprite sheets, class files, and data files.

TexturePacker Loader

Before starting work on our demo app, let’s take a minute to look at the TexturePacker Loader. This can currently be downloaded freely, along with the source code, from GitHub and NuGet, with Xamarin also planning to add it to its component store.

The TexturePacker Loader source code is composed of just four files. Therefore, it’s easy for beginners to understand, and it’s easy for pros to make modifications.

texturepacker loader project files

Instead of covering every detail of the TexturePacker Loader, right now we’re just going to go over what’s relevant for this demo.

Sprite Sheet Loader

Since we’ll be creating a new MonoGame app, we want to start by loading our sprite sheets (and any other assets). This is usually done in the LoadContent method of our main Game class.


To do this, we’ll need to instantiate a new instance of the SpriteSheetLoader class and call the Load method passing in the name of your sprite sheet (as produced by TexturePacker). Below is an example:

var spriteSheetLoader = new SpriteSheetLoader(this.Content);
this.spriteSheet = spriteSheetLoader.Load("CapGuyDemo.png");

This will create a reference to a sprite sheet. We’d suggest this is a class level variable as it will be required in your draw method as described below:

Sprite Render

We also must utilize the SpriteRender class, which controls the drawing and positioning of on-screen sprites. Beginning users need only to identify which image they wish to use and what position it should be in. More advanced users, however, have the ability to greatly customize the rendering, with the ability to control the image’s color, rotation, and scale, as well as flip the image.

We would recommend instantiating one instance of this class in your LoadContent method, as seen below:

this.spriteBatch = new SpriteBatch(GraphicsDevice);
this.spriteRender = new SpriteRender(this.spriteBatch);

And then in your draw method you simply render frames on screen, something like this:

this.spriteBatch.Begin();

this.spriteRender.Draw(
    this.spriteSheet.Sprite(
        TexturePackerMonoGameDefinitions.CapGuyDemo.Capguy_turn_0002
    ),
    new Vector2(350, 530)
);

this.spriteBatch.End();

As you can see in the example above, we are drawing Capguy_turn_0002 at location 350, 530.

When we originally exported the TexturePacker files, one of the files we exported was the Class file, which defined each individual sprite’s constant values. Here’s where that comes into play. Using this method rather than the string value ensures that, should an image file be missing from the sprite sheet, a compile time error will occur. This is preferable to a runtime error, which may not occur until deployment, and therefore, may be more complicated to fix.

This is all we need to know in order to get started with rendering. TexturePacker Loader’s code ensures that sprites appear correctly, even if they’ve been rotated or trimmed on the sprite sheet itself. All we need to do is let it know which frame to render and where we want it!

Now that we have a better understanding of TexturePacker and TexturePacker Loader, we can start integrating it with MonoGame!


Below we have two MonoGame examples – one using Visual Studio to create a Windows 8 Store App, and another using Xamarin Studio to create an iOS app.

You also have the option of downloading a complete example from GitHub to study it in its entirety.

MonoGame

The main goal of MonoGame is to enable simpler cross-platform game development. Instead of using different standards for each platform, MonoGame allows C# development for one platform, and then requires only minor adjustments to make it compatible with other platforms.

MonoGame is incredibly versatile, and can currently be used for such powerhouse platforms as Windows, Windows Phone, Xbox 360, Android, iOS, OS X, and Linux, with development currently under way for PlayStation 4, PlayStation Mobile, and Raspberry Pi.

In the demo app we are going to create here, we will animate “CapGuy” walking across the screen. Our first example will be with Visual Studio for Windows 8, so if you prefer Xamarin for iOS, then feel free to skip ahead to the next section.

MonoGame Windows Store Example with Visual Studio

There are two methods for using MonoGame with Visual Studio. Neither is particularly better than the other, it just depends on your personal preference.

The first method is to go to MonoGame and use the Windows installer. This will add an option for MonoGame in the template list for new projects. Just select MonoGame Windows Store Project to quickly and easily get started on your project!

windows monogame create project

The other method is to simply start a new standard Windows Store project, then go to NuGet and install the package from there.

windows monogame nuget

Now we can build and run the solution, resulting in a “cornflower blue” screen. If that’s what you get, then everything is working correctly!

Next we need to add our Texture, Data, and Class files from TexturePacker.

To do this, first ensure that the Texture file and Data file are in the Content folder. We then mark their “build action” as “Content.”

windows monogame datafile properties

Doing this guarantees that we’ll be able to access this data at run-time.

The SpriteNames.cs file is not required to be in any specific location – it can go anywhere you choose.

In order to work with the data files from TexturePacker, we now need to use the TexturePacker Loader. We can get this from NuGet, so in Solution Explorer right click on References and then click on Manage NuGet Packages.

windows monogame loader nuget

Then simply install the TexturePacker package.

windows monogame loader nuget search

NuGet packages normally consist of a library DLL that will then be referenced in your project, but with TexturePacker Loader, NuGet actually gives you the complete source code.

texturepacker loader project files

At this point we’ve got everything we need from TexturePacker – all of our files (texture, data, and class) as well as the TexturePacker Loader, so let’s start using it! Now let’s download GitHub’s demo package.

Once you’ve loaded up the solution, this is what you should see:

windows monogame visual studio

All you need to do is hit the F5 key to make CapGuy walk back and forth across the screen. It may not seem like much, but considering the minimal amount of code used here, it’s really pretty impressive!

Next up, we’ll do the same program in Xamarin Studio for use on an iOS device, and after that, there’s a section which takes a more in-depth look at the demo app and how it works.

MonoGame iPad Example with Xamarin Studio

We have a few options for getting MonoGame to work with Xamarin Studio, but using the NuGet package is probably the most convenient, as it simplifies updating MonoGame when new updates are available.

Start by opening Xamarin Studio, selecting iPad and then clicking on Empty Project.

xamarin new project

Next click the Project dropdown menu and select Add Packages.

xamarin about to add package

A NuGet window will appear. Select MonoGame.

xamarin nuget package list

There will be more than one option for MonoGame, but the one you should choose is simply called MonoGame (highlighted above). This package contains the required binaries as well as sample code.

After the MonoGame package has finished installing, a Packages folder will appear in our solution. This will also install some source files – Game1.cs and GameMain.cs.

xamarin after nuget added

At this point, we must delete the AppDelegate.cs and Main.cs files, as the Game1.cs and GameMain.cs will take their place.

We next need to add a reference to the NuGet package by right clicking on References and then selecting Edit References, which will bring up the screen below:

xamarin add reference

Now click the Net Assembly tab and open the MonoTouch folder in the MonoGame.Binaries package. Select the file MonoGame.Framework.dll and click Add then OK.

We should now get a cornflower blue screen when we try to run our solution.

Next we need to add out files from TexturePacker.

If you haven’t done so already, create a folder called Content and put all TexturePacker texture and data files in it, then add these files to the solution. Make sure that the Build action is set to BundleResource – this is usually automatic for png format, but not always for txt files. The BundleResource option ensures that the files can be accessed at run-time.

In the Content folder, we should now have two sets of files – one set with @2x at the end of the filename, and one set without. Again, the @2x files are used for Retina displays, while the other files are for non-Retina displays. This is done automatically – there is no need to code for it.

xamarin content properties

The SpriteNames.cs file does not need to be in any particular location – you can put it wherever you choose.

Now it’s time to use TexturePacker Loader so that we can actually use our TexturePacker files with this project. We can get this from NuGet by clicking Project and Add Packages. Find the TexturePacker package and install it.

xamarin nuget texturepacker

NuGet packages normally consist of a library DLL that will then be referenced in your project, but with TexturePacker Loader, NuGet actually gives you the complete source code.

xamarin texturepacker references

At this point we’ve got everything we need from TexturePacker – all of our files (texture, data, and class) as well as the TexturePacker Loader, so let’s start using it! Now let’s download the demo package from GitHub.

Once you’ve loaded up the solution, this is what you should see:

xamarin full solution

Now just click the Run button (Play/triangle), and CapGuy will walk back and forth across the screen.

The next section explores the demo code in much more detail.

DemoGame

Congrats on your demo! We hope you’ve been enjoying this exercise!

This section of the tutorial doesn’t focus on TexturePacker or MonoGame, but on the demo app itself. Here we cover some of the other classes that you may want to use for other projects.

Most of the code in the demo should be pretty easy to understand, but what about the InitialiseAnimationManager() method? This is what defines CapGuy’s animation. It controls where on the screen he starts as well as his speed. On iOS this can also be affected by whether or not the device has a Retina display.

#if __IOS__
    var scale = MonoTouch.UIKit.UIScreen.MainScreen.Scale;
    var characterStartPosition = new Vector2(350 * scale, 530 * scale);
    var characterVelocityPixelsPerSecond = 200 * (int)scale;
#else
    var characterStartPosition = new Vector2(350, 530);
    var characterVelocityPixelsPerSecond = 200;
#endif

Here two local variables are created that consist of arrays of frame names. These arrays define the frames that compose movement sequences, like walking or turning.

var turnSprites = new [] {
    TexturePackerMonoGameDefinitions.CapGuyDemo.Capguy_turn_0001,
    TexturePackerMonoGameDefinitions.CapGuyDemo.Capguy_turn_0002,
    TexturePackerMonoGameDefinitions.CapGuyDemo.Capguy_turn_0003,
    TexturePackerMonoGameDefinitions.CapGuyDemo.Capguy_turn_0004,
    ...

In addition to the sequence of frames, there are also a number of other variables that we can control here. We can specify the sprite’s velocity, amount of time before switching frames, and flipping the frames (which direction the sprite is facing). This is everything we need to define our animation. Here’s what the code looks like:

var animationWalkRight = 
    new Animation(
        new Vector2(characterVelocityPixelsPerSecond, 0), 
        this.timePerFrame, SpriteEffects.None, walkSprites
    );
var animationWalkLeft = 
    new Animation(
        new Vector2(-characterVelocityPixelsPerSecond, 0), 
        this.timePerFrame, SpriteEffects.FlipHorizontally, walkSprites
    );
var animationTurnRightToLeft = 
    new Animation(
        Vector2.Zero, this.timePerFrame, SpriteEffects.None, turnSprites
    );
var animationTurnLeftToRight = 
    new Animation(
        Vector2.Zero, this.timePerFrame, 
        SpriteEffects.FlipHorizontally, turnSprites
    );

So we now defined four types of animation – walking left, walking right, turning left, and turning right. By putting this together in sequence, we can create a continuous loop of CapGuy walking back and forth across the screen.

var animations = new[] 
{ 
   animationWalkRight, animationWalkRight, animationWalkRight,
   animationWalkRight, animationWalkRight, animationWalkRight,
   animationTurnRightToLeft,
   animationWalkLeft, animationWalkLeft, animationWalkLeft,
   animationWalkLeft, animationWalkLeft, animationWalkLeft, 
   animationTurnLeftToRight
};

In this example, the “walk right” animation will repeat six times before he turns and the “walk left” animation will repeat six times, and so on.

We now need to create an instance of the AnimationManager class passing in all of this information.

this.characterAnimationManager = new AnimationManager (
    this.spriteSheet, characterStartPosition, animations
);

After that’s done, we can just call the AnimationManager’s update method each game loop.

protected override void Update(GameTime gameTime)
{
    this.characterAnimationManager.Update(gameTime);

    base.Update(gameTime);
}

Then we just need to use AnimationManager to make sure that our images are correct – proper sprite and effects in the proper position and Draw method.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.Black);

    this.spriteBatch.Begin();

    // Draw the background
    this.spriteRender.Draw(this.backgroundSprite, this.centreScreen);

    // Draw character on screen
    this.spriteRender.Draw(
        this.characterAnimationManager.CurrentSprite, 
        this.characterAnimationManager.CurrentPosition, 
        Color.White, 0, 1,
        this.characterAnimationManager.CurrentSpriteEffects);

    this.spriteBatch.End();

    base.Draw(gameTime);
}

There are other ways to handle the animation, and there may be other methods that you prefer, but you’re welcome to use this code, if you’d like!

The End

We hope you enjoyed this tutorial and were able to learn something new, or just get a little more practice!

If you’d like to see the finished product without having to build it yourself, here’s a video of the completed demo on iOS:

Eventually the TexturePacker Loader will be published to the Xamarin Component Store, so when that happens, look for an update from us!

Did you like the tutorial? Please share!

Source code available for download

The source code is available on GitHub. Clone it using git:

git clone https://github.com/CodeAndWeb/TexturePacker-MonoGame-Demo.git

or download one of the archives:
TexturePacker-MonoGame-Demo.zip TexturePacker-MonoGame-Demo.tar.gz