Finite State Machines
Have you ever heard of the term "Finite State Machine" or seen the acronym FSM and wondered what exactly it is? In short it is an important, and powerful, coding concept that can enhance the extendability of your code.
To expand on my earlier post about enumerations I'm going to look at Finite State Machines in a relatively general sense. Let's start with breaking down what exactly a Finite State Machine is. We can look at the descriptive words to see that it is a machine, or system, that consists of a finite number of states. Great, but what does that mean? In a sense it is a way to package your code so only the desired pieces run at the desired time, this makes them very useful for succinct organization. In the rest of the article we'll look at different ways to implement the system, as well as the pros and cons of each.
The first thing to look at is how to define the states within the machine. Many coders will jump to strings as they allow infinite descriptive variation for the states. Another option is to use numbers to label the states. The real question is, why not take advantage of both? I strongly recommend using enums for states whenever possible, they give you the descriptiveness of strings while retaining the efficiency of numbers. Since enums are technically numbers you can increment (++) and decrement (--) them, but refer to them by a text definition.
There are also a few different ways to actually make a state machine. A state machine usually will reside within the main loops of an object, or its update function if it has one. Popular ways to do a state machine include either a switch statement, or if, else tree:
public void Update(){ switch (state) { case State.state1: // TODO break; case State.state2: // TODO break; default: // etc. } if (state == State.state1) { // TODO } else if (state == State.state2) { // TODO } else { // etc. }}
Here is where I disagree. Instead of a switch or if, else tree I think that it is important to keep the states as separate if statements. This way when your logic changes the state, you can compute the next state right away instead of waiting for the next update. Sometimes you may want to wait for the next update for some particular reason, but typically this is not necessary. While this only works for states going up the tree in progression, you can very easily structure your program as it is below thereby making sure all logic is complete before continuing.
public void Update(){ bool done = true; do { if (state == State.state1) { done = DoState1(); } if (state == State.state2) { done = DoState2(); } if (state == State.state3) { done = DoState3(); } // etc. } while(!done);}
You may have noticed that I am calling functions for each state. I firmly believe in having a modular approach to one's code. It's better to break it off into a function and end up only having one place calling it, then to have to restructure it into a function later. It's also a lot easier to take advantage of return to only use as much of the code as you need. With the functional approach you can also call the logic of an earlier state in a later state if you happen to switch states, or need to correct any missing data. Enclosing your state machine within a while block is really not necessary, but it can allow you to have less frequent update functions and not waste an update cycle on a change.
In a nutshell this is what makes a FSM (everything has an acronym). Your game, or object, works on a series of states thereby limiting the code needed to run. States help keep things well organized and can even prevent erroneous errors bleeding in from rogue code by limiting exposure. Later I will get into the importance of Classes and Object/Aspect oriented programming (OOP / AOP) and how important organization and convention is.
Read more about:
BlogsAbout the Author
You May Also Like