Finite State Machines for Game Developers

Finite State Machines for Game Developers

Several of the games I'm working on require the use of finite state machines for believable AI. For example, the game Pounce is using an FSM for the mice characters as they scurry around the level. Using them in games makes the AI characters seem more believable and help them react to many different situations. In fact they are used frequently in AAA game titles for bots and other autonomous characters. So just how do we implement them in our own games?

First thing is to define a list of states we'll be using. It doesn't have to be complete at first, just a few that pop into your head. So I'm going to be using mice as an example from my game Pounce. The states I came up with are Scout, Roam, and Flee. The scout state will have the mouse check if a cat is around, the roam state is simply a walking state, and the flee state is a faster walk motion.

Mouse States

Now that we have a few states to play with we need to understand how they are related to each other. Obviously if the mouse sees a cat in the Scout state then we are going to flee away from the cat. If we're in the flee state and we're far enough from the cat we'll switch to idle, and if the cat is in front of the mouse when we're roaming then we switch to flee. Here's a diagram to show the relationships.

Finite State Machine

So just how do we go about coding this state machine? Well first we need to have a state variable that holds the information about the current state we're in. We also need to check each frame if the conditions are met to switch to a different state. So instead of explain it all in this document I'm going to show you an example class that implements our mouse finite state machine. This example is not fully functional but will give you an idea of how to implement it yourself. It is written in Actionscript 3.0.

package
{

    public class Mouse
    {

        // Create a static constant for each state
        private static const kStateSearch:int = 0;
        private static const kStateRoam:int = 1;
        private static const kStateFlee:int = 2;

        // Holds the current state id
        private var _state:int;

        public function Mouse()
        {
            // Set the initial state
            switchState(kStateRoam);
        }

        // This function will initialize any variables when we switch states
        public function switchState(state:int)
        {
            switch(state)
            {
                case kStateSearch:
                    doneSearching = false;
                    break;
                case kStateRoam:
                    speed = kWalkSpeed;
                    break;
                case kStateFlee:
                    speed = kFleeSpeed;
                    break;
            }
            _state = state;
        }

        // Needs to be called every frame to update the state we're on
        public function updateState()
        {
            switch(_state)
            {
                case kStateSearch:
                    // Did the cat get close again?
                    if (distanceToCat < 100)
                    {
                        switchState(kStateFlee);
                    }
                    // Am I done looking around (not paranoid anymore)
                    if (doneSearching)
                    {
                        switchState(kStateRoam);
                    }
                    break;
                case kStateRoam:
                    // Did the cat jump in front of me?
                    if (catInFront)
                    {
                        switchState(kStateFlee);
                    }
                    break;
                case kStateFlee:
                    // Finally got away from the cat...
                    if (distanceToCat > 200)
                    {
                        switchState(kStateSearch);
                    }
                    break;
            }
        }

    }

}

Posted in AS3 Tutorials

Tags: Actionscript, Flash, Pounce, AI

comments powered by Disqus