Gamasutra is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.

Press Releases
September 20, 2019
Games Press

If you enjoy reading this site, you might also want to check out these UBM Tech sites:

# Building A Better Animation System in GameMaker: Studio

by Nathan Ranney on 05/08/17 11:46:00 am

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

When developing Kerfuffle I needed an animation system that would allow me to hold any individual frame of animation for as long as I wanted in game, without having to manually add or remove frames to the sprite. I also needed to be able to trigger certain actions based on the current animation frame. Using this setup I was able to create hitboxes, play sounds, or change states, all while having full control over everything being drawn on the screen.

## Variables

These are the important variables associated with the animation system. Refer back to this if you get confused.

frameSpeed
The speed in FPS that the game counts through the frames to be displayed. Default is 1.

frameCounter
Increases every frame by the frameSpeed.

currentFrame
The frame of the sprite currently being drawn on the screen.

frameData
Current list of frame data the game is reading from, based on the animation that needs to play. Idle, run, attack, etc.

frameDuration
Total number of in game frames to display the current sprite frame.

maxFrames
The total number of frames in any given sprite.

animSprite
The actual name of the sprite resource in GameMaker. sprMomo_Idle, for example.

## Helper Scripts

A couple of useful scripts that save us some typing later.

frame_reset();
Resets frameCounter and currentFrame to 0.

frameCounter = 0;
currentFrame = 0;

animation_set();
This script accepts two arguments. First, the frameData (which is the relevant list of frame data) and second is the animSprite (the sprite resource you want to draw).

//animation_set ( argument0, argument1 );

frameData = argument0;
animSprite = argument1;

## Frame Data

Each animation requires a list of frame data. This is a list that contains the amount of in game frames that each frame of animation will be played. Each list of data uses the following naming convention. frameDataIdle, frameDataRun, frameDataDash, and so on. Also, if anyone knows how to use a table in tumblr… please tell me how.

Frame data for Momo’s idle animation

Animation Frame # Of Frames to be Displayed
00 5
01 9
02 3
03 3
04 3
05 3
06 5
07 9
08 3
09 3
10 3
11 3

Be aware that all lists, and values, start with 0. So even though this animation has 12 frames, the highest number in the list is 11. This includes frames you want to display! If you want it to show up for 5 frames in game, the value in the list should be 4.

**GameMaker Specific Note**
Make sure you manually delete a list when you are no longer using it! Otherwise you can run into memory leaks!

## Frame Counter

Now that we have a list of frame data, we need to actually animate based on that data. The first thing we need to do is figure out what the maxFrames are.

maxFrames = sprite_get_number( animSprite ) - 1;

Then, if your currentFrame happens to be greater than or equal to max frames, AND frameCounter is greater than or equal to the maximum number of frames the sprite frame should appear on screen, reset to the first frame.

if ( currentFrame >= maxFrames - 1 && frameCounter == frameDuration )Â
{
Â  Â  Â frame_reset();
}

Now the frameCounter can do its job. It counts up to the number of frames the current frame of the sprite should be displayed, then once it reaches that maximum, ticks the currentFrame up to the next frame of of the sprite, and resets back to 0 to start counting again.

frameCounter += frameSpeed;

frameDuration = ds_list_find_value ( frameData, currentFrame );

if ( frameCounter == frameDuration )
{
Â  Â  Â currentFrame ++;
Â  Â  Â frameCounter = 0;
}

Side Note:
Using maxFrames is also a good way to end animations, and change to a new animation or state! I use maxFrames to switch from an attack state back to the normal state after the entire attack animation has played all the way through.

**GameMaker Specific Note**
Sprite_get_number is a built in GameMaker function that returns the number of frames in a sprite. This function returns the exact number of frames, and does not count up from 0! So if you have a sprite with 5 frames, this will return 5! This is why when checking against maxFrames, we do so while subtracting 1 from its value.

## Switching Sprites

Everything in Kerfuffle runs on a fairly simple state machine. Depending on the state the character is in, the animation changes.

//store the current animation sprite so we can check it later
currentAnim = animSprite;

switch ( state ) {
Â  Â  Â case normal:
Â  Â  Â  Â  Â  //if the player is pushing left, or right, change to run sprite
Â  Â  Â  Â  Â  if ( left || right )
Â  Â  Â  Â  Â  {
Â  Â  Â  Â  Â  Â  Â  Â animation_set ( frameDataRun, runSprite );
Â  Â  Â  Â  Â  Â  Â  Â //if the player isn’t pushing any buttons, change to idle sprite
Â  Â  Â  Â  Â  } else {
Â  Â  Â  Â  Â  Â  Â  Â animation_set ( frameDataIdle, idleSprite );
Â  Â  Â  Â  Â  }
Â  Â  Â break;

Â  Â  Â case dash:
Â  Â  Â  Â  Â  //if the player is in the dash state, change to the dash sprite
Â  Â  Â  Â  Â  animation_set ( frameDataDash, dashSprite );
Â  Â  Â break;
}

//check the current animation against the last animation.
//If these animations are NOT the same, reset frameCounter and currentFrame to 0.

if(lastAnim != currentAnim)
{
Â  Â  Â frame_reset();
Â  Â  Â lastAnim = currentAnim;
}

**GameMaker Specific Note**
Use macros or enums instead of strings where possible. I used to use strings for player states (ie: “normal” instead of just normal) and it’s not the best idea. Strings are slower to process, and if you make a typo, GameMaker will not alert you! Your code will just fail and it is much easier to overlook!

For more info on Macros check out this write up by YellowAfterLife.
https://yal.cc/gamemaker-on-global-variables/

## Putting It To Use

Now that all of this has been setup, we just need to put it to use. Since we are bypassing GameMakers built in functions like image_speed and sprite_index, we need to draw the sprites ourselves. This is really easy though! We just need to use draw_sprite_ext!

//draw event

draw_sprite_ext ( animSprite, currentFrame, x, y, 1, 1, 0, c_white, 1 );

For more info on exactly what draw_sprite_ext does check out the GameMaker documentation. There are a lot of great things you can do with this! In my opinion its one of the most important parts of GameMaker that you should learn!

## Final Thoughts

So thats it! Pretty easy right? If you have any questions, or comments on how to improve this, please let me know. I will respond as soon as I am able. If there are any other write-ups like this that you’d like to see, let me know what they are!

Check out my games on Itch.io!

Later, Nerds

### Related Jobs

HB Studios — Lunenburg/Halifax, Nova Scotia, Canada
[09.20.19]

Experienced Software Engineer
University of Exeter — Exeter, England, United Kingdom
[09.20.19]

Serious Games Developer
innogames — Hamburg, Germany
[09.20.19]

PHP Developer - Tribal Wars
innogames — Hamburg, Germany
[09.20.19]

Java Software Developer - New Mobile Game