O'Reilly logo

Programming Game AI by Example by Mat Buckland

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Global States and State Blips
More often than not, when designing finite state machines you will end up
with code that is duplicated in every state. For example, in the popular
game The Sims by Maxis, a Sim may feel the urge of nature come upon it
and have to visit the bathroom to relieve itself. This urge may occur in any
state the Sim may be in and at any time. Given the current design, to
bestow the gold miner with this type of behavior, duplicate conditional
logic would have to be added to every one of his states, or alternatively,
placed into the
Miner::Update function. While the latter solution is accept
-
able, it’s better to create a global state that is called every time the FSM is
updated. That way, all the logic for the FSM is contained within the states
and not in the agent class that owns the FSM.
To implement a global state, an additional member variable is required:
//notice how now that State is a class template we have to declare the entity type
State<Miner>* m_pGlobalState;
In addition to global behavior, occasionally it will be convenient for an
agent to enter a state with the condition that when the state is exited, the
agent returns to its previous state. I call this behavior a state blip. For
example, just as in The Sims, you may insist that your agent can visit the
bathroom at any time, yet make sure it always returns to its prior state. To
give an FSM this type of functionality it must keep a record of the previous
state so the state blip can revert to it. This is easy to do as all that is
required is another member variable and some additional logic in the
Miner::ChangeState method.
By now though, to implement these additions, the
Miner class has
acquired two extra member variables and one additional method. It has
ended up looking something like this (extraneous detail omitted):
class Miner : public BaseGameEntity
{
private:
State<Miner>* m_pCurrentState;
State<Miner>* m_pPreviousState;
State<Miner>* m_pGlobalState;
...
public:
void ChangeState(State<Miner>* pNewState);
void RevertToPreviousState();
...
};
Hmm, looks like it’s time to tidy up a little.
State-Driven Agent Design | 63
Global States and State Blips

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required