Monthly Archives: October 2014

The basics of state machines in GameMaker (Updated with better descriptions and visual aids)

One way to really keep your code organized in any engine for any type of game or simulation is to use something called a finite state machine, or just state machine for short.


What is a state machine?

As Wikipedia defines it:

A mathematical model of computation used to design both computer programs and sequential logic circuits. It is conceived as an abstract machine that can be in one of a finite number of states.

In layman’s terms, it’s a type of code structure based on fancy-shmancy flowcharts like this one:

state machine 2

Whipped this up in about a minute thanks to this nifty tool.

The general idea is that at any given time, your system is in one of several states defined by a distinct set of behavior. When certain conditions are met or certain actions are performed, the system will transition to another state.

You can use state machines for all sorts of things, but they’re particularly helpful for structuring menus, AI and character movement.


Visualizing a state machine:

Let’s say we want to make a state machine for a basic 2D platformer in which the player can move left and right, jump and grab corners. I tend to make a state for each type of movement — idle, walking, jumping, falling and hanging — but to keep things simple we can set up our state machine based on three sets of physics:

  • The Ground physics (horizontal movement only),
  • The Air physics (horizontal and vertical movement with gravity), and
  • The Hanging physics (no movement, you’re just snapped to the ledge)

So each of those is a separate state and actions like jumping, falling off ledges, etc. are the transitions. The state machine would look something like this:

state machine


Implementing the state machine:

Some game engines have their own state machine systems, or at least visual scripting tools that can be used to set up state machines. Unity, for example, has the Mecanim animation system. GameMaker has no such tool, but it’s easy to set up one with GML code. We’ll use the platformer example we just came up with.

First, add an enumeration at the start of the game to use as a shorthand for the different states:

enum STATE_PHYSICAL
{
    ground,
    air,
    hanging
    // Etc.
}

Next, define the current state variable in your player object’s Create event:

myState_Physical = STATE_PHYSICAL.ground;

And finally, put a switch statement in the Step event with a case for each state:

switch (myState_Physical)
{
    case STATE_PHYSICAL.ground:
    {
        Script_PhysState_Ground ();
    }; break;
    
    case STATE_PHYSICAL.air:
    {
        Script_PhysState_Air ();
    }; break;
    
    case STATE_PHYSICAL.hanging:
    {
        // Etc.
    }; break;
}

That switch statement is essentially a bunch of if statements mashed together; it only processes a case if myState_Physical is equal to the given value, so if the player’s current state is STATE_PHYSICAL.ground it’ll call Script_PhysState_Ground (), if their state is STATE_PHYSICAL.air it’ll call the Air script, and so on and so forth.

And that’s really all there is to it! The transitions can be handled in a number of different ways; they could be as simple as setting the current state variable to a new value, or you could define scripts for switching to and from specific states. The important thing is that you have your code divided up in a logical, readable and manageable manner.


Additional notes:

Here’s a few other suggestions on using state machines effectively:

  • Depending on how complex and nuanced your character’s behavior is, you may want to define the behavior and transitions in a script for each state like I did above.
    • In fact, it might be best to store each script in a variable and call them with script_execute(); that way you only need to define the state machine in a parent object and you can change the behavior of the children by simply changing a few variables in their Create event.
  • Remember that you can use state machines for all sorts of mechanics, not just AI and movement:
    enum STATE_CONTROL
    {
        none,
        player,
        cpu
    }
    
    enum STATE_FACTION
    {
        ally,
        enemy,
        neutral
    }
    
    enum STATE_COMBAT
    {
        idle,
        attack,
        block,
        hurt,
        stunned
    }
    
    enum STATE_DAMAGE
    {
        vulnerable,
        mercy,
        invincible,
        dead
    }
    
    enum STATE_INPUT
    {
        up,
        press,
        down,
        release
    }
    
    enum STATE_ANIM
    {
        idle,
        weakIdle,
        dead,
        walk,
        run,
        jump,
        fall,
        hurt,
        punch,
        kick,
        stunned,
        victory,
        defeat,
        happy
        // Etc.
    }

I may add some other suggestions as they come to mind. For now, happy gamedev! 😉

Advertisements