Tutorials Icon

Tutorials > MonoGame - How to Use Sprite Sheets

MonoGame - How to Use Sprite Sheets

By Stephen Armstrong // February 18, 2020


Learn about using sprite sheets to consolidate your graphics and to enable animation.

In this tutorial we assume you have completed the following tutorial and added/loaded the Texture2D "charaset" to your project.
https://www.industrian.net/tutorials/texture2d-and-drawing-sprites/

The following C# code will show you how to use sprite sheets to display graphics in a MonoGame project.

A 2D game requires a lot of sprites for characters and levels. To greatly simplify the number of graphical assets you need to load and keep track of, it’s easier to bundle related sprites into a single image file. This is called a sprite sheet – or alternatively a texture atlas, character set, chipset, or other terms.

For this example we’re returning to Alex, our good friend from RPGMaker 2000. As you can see from the below image (and from previous tutorials) this texture contains his entire up, right, down, and left movement animation.

Alex from RPGMaker 2000.

Setting a sourceRectangle

In spriteBatch.Draw() you can set a sourceRectangle. This tells the game to only draw the part of the texture within the sourceRectangle.

To give a quick example, use the following code:

// Draw the entire sprite.
spriteBatch.Draw(charaset, new Vector2(100, 100), Color.White);

// Create a sourceRectangle.
Rectangle sourceRectangle = new Rectangle(0, 0, 48, 64);

// Only draw the area contained within the sourceRectangle.
spriteBatch.Draw(charaset, new Vector2(300, 100), sourceRectangle, Color.White);

Now run the code, and you’ll see both the full texture, and one that has the sourceRectangle for the top-left sprite.

Alex from RPGMaker 2000.

It’s that easy to get an individual sprite from a sprite sheet!

As long as you know the X and Y position of where sprites appear on the sprite sheet – and their width and height – then you can reliably draw them whenever needed.

Simple Animation with Sprite Sheets

The following is a very basic example of how to animate sprites with sprite sheets.

First, go to Game1 and add the following fields:

// A timer that stores milliseconds.
float timer;

// An int that is the threshold for the timer.
int threshold;

// A Rectangle array that stores sourceRectangles for animations.
Rectangle [] sourceRectangles;

// These bytes tell the spriteBatch.Draw() what sourceRectangle to display.
byte previousAnimationIndex;
byte currentAnimationIndex;

Go to LoadContent() and enter the default values for these fields:

// Set a default timer value.
timer = 0;

// Set an initial threshold of 250ms, you can change this to alter the speed of the animation (lower number = faster animation).
threshold = 250;

// Three sourceRectangles contain the coordinates of Alex's three down-facing sprites on the charaset.
sourceRectangles = new Rectangle[3];
sourceRectangles[0] = new Rectangle(0, 128, 48, 64);
sourceRectangles[1] = new Rectangle(48, 128, 48, 64);
sourceRectangles[2] = new Rectangle(96, 128, 48, 64);

// This tells the animation to start on the left-side sprite.
previousAnimationIndex = 2;
currentAnimationIndex = 1;

Go to Draw() and add this simple code to draw the animated sprite:

// Draw the sprite based on the sourceRectangle and currentAnimationIndex .
spriteBatch.Draw(charaset, new Vector2(100, 100), sourceRectangles[currentAnimationIndex], Color.White);

Finally, here comes the logic for animation. Go to Update() and add the following code:

// Check if the timer has exceeded the threshold.
if (timer > threshold)
{
    // If Alex is in the middle sprite of the animation.
    if (currentAnimationIndex == 1)
    {
        // If the previous animation was the left-side sprite, then the next animation should be the right-side sprite.
        if (previousAnimationIndex == 0)
        {
            currentAnimationIndex = 2;
        }
        else
        
        // If not, then the next animation should be the left-side sprite.
        {
            currentAnimationIndex = 0;
        }
        
        // Track the animation.
        previousAnimationIndex = currentAnimationIndex;
    }
    // If Alex was not in the middle sprite of the animation, he should return to the middle sprite.
    else
    {
        currentAnimationIndex = 1;
    }
    
    // Reset the timer.
    timer = 0;
}
// If the timer has not reached the threshold, then add the milliseconds that have past since the last Update() to the timer.
else
{
    timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
}

Now run your code, and you will see Alex walking on the spot.

Alex from RPGMaker 2000 animated.

This is a very simple-but-effective example of how convenient sprite sheets can be. It is also a good start for learning about sprite animation.

Further Reading

Future articles will go into further detail regarding animation and greater use of sprite sheets.

< Go back

Return to top of page

Article Icon

Welcome to Industrian.net!

On this website you'll find more information about our games, and also some tutorials for you to start making games of your own! You can also follow us on various social platforms!