woensdag 22 februari 2012
In our games we often have to program characters that need specific behaviors. To keep the code clean and understandable we use (finite-) state machines for this. State machines are systems with states and transitions. The machine can only be in a single state at any one time. Changes between the states are called transitions. As certain conditions hold these transitions are made.
For example suppose we have a character that can idle, walk, jump and die. These are our states. Now we define (draw) our transition based on how we want the character to work. Lets say that the character can only jump when he's walking and not when he's idle. He can die in any state and after dying he's brought back to life in his idle state. The state machine would then look like this:
We then still need to determine when the transitions are made: the conditions for each transition. From Idle to Walking it could be whether the user presses either the left or right key. And from Walking to Idle when the user no longer presses the left or right key. From any state to Die we could check whether a variable 'touchedByEnemy' is set to true (which we set to true whenever we detected the character touched an enemy). Between Walk and Jump the condition can be if the user presses the up key. Between Jump and Walk we check if the character touches the ground again. And finally from Die to Idle which can be whenever the dying animation stopped playing.
Of course the example here is relatively simple as you get more states you're bound to get more transitions and too many transitions will clutter your drawing making it less comprehensible. There are some tricks you can do to avoid this such as drawing a circle around a couple of states and drawing a single transition from here indicating that it is a transition from all of those states. You could also introduce a second state machine. If for example the player in any state can carry a shield you don't want to copy each state and draw the same transitions between them. Instead you make a second state machine for the shield with in this case only 2 states: Unshielded and Shielded.
Drawing a state machine based on the desired behavior helps me as a programmer to maintain overview which makes it easier when changes need to be made in the behavior. It will also help other programmers should they have to work with my code.