7
\$\begingroup\$

I don't understand how to use a finite state machine with the entity controlled by the player.

For example I have a Mario style game (2d platform). I can jump, run, walk, take damage, swim, etc. So my first thought was to use this actions as states. But what happens, if you are running when you take damage? Or jumping, taking damage and shooting at the same time?

I just want to add functionalities (actions) to the player in a clean way (not using it for all the actions in the entity update) .

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The question is somewhat bizarre; why would actions be states in the FSM? Why wouldn't they be inputs to the FSM? \$\endgroup\$
    – Eric Lippert
    Jan 30, 2011 at 19:58

2 Answers 2

7
\$\begingroup\$

I guess the normal way is to have multiple state machines. This way you can stick to atomic states which often makes your live a lot easier than having to deal with complex states.

For example:

  • Damage Mode: Normal, Invulnerable (as in just hit), invincible (as in got a star)
  • Pace: Walking Mode, Running Mode
  • Abilities: Normal, Super, Fire, Fly
  • Movement Type: Walking, Swimming, Flying

In object oriented designed there is the sate pattern for this. It boils down to having one interface per state machine. And a class per possible state which implements this interface.

To give an example: There would be an interface DamageMode and subclasses NormalDamageMode, InvulnerableDamageMode and InvincibleDamageMode. Whenever the player collidates with an enemy the method DamageMode.collision(enemy) is called. It is handled by the class responsible for the current state.

So if damageMode == NormalDamageMode the player will be damaged and the state variable will be set to InvulnerableDamageMode. In InvulnerableDamageMode nothing happens and in InvincibleDamageMode the enemy will be damaged. Of course there needs to be timers to go back from InvulnerableDamageMode and InvincibleDamageMode to NormalDamageMode.

The main advantage of the state pattern compared to if-elseif-elseif-elseif-blocks is that it allows to structure your code better.

\$\endgroup\$
3
  • \$\begingroup\$ +1 for making many small FSMs, rather than one big 'un. Grainularity is very useful here. \$\endgroup\$
    – tenpn
    Apr 11, 2011 at 8:26
  • \$\begingroup\$ I like the idea of multiple state machines. But how are they integrated to work with an entity? Are they updated in parallel? or are they nested inside an entity state machine? \$\endgroup\$
    – Dani
    May 4, 2011 at 16:46
  • \$\begingroup\$ @Dani, each state machines is referenced as an attribute of the entity objects. Most of them are independent for example, you can be invincible with small, super, fire and fly Abilities. Some events trigger multiple state transitions: For example getting hit by an enemy will decrease the ability and change damage mode to invulnerable. This leaves only a few cases where two state machines are actually linked. For example force run mode while invincible. \$\endgroup\$ May 4, 2011 at 17:44
7
\$\begingroup\$

States are not actions, in your game they would control how the character is updated (e.g. each state could have its own update() function).

Take a look at the diagram on this page: http://en.wikipedia.org/wiki/State_diagram. The states tell us something about the world (the door is open or closed). The actions show us what takes the world from one state to another.

In your case you could have states like:

  • jumping
  • running
  • in pain
  • falling
  • dead

And the transition between states (the events / arrows between states) would be player inputs and reactions to the world, such as:

  • hit by monster
  • jump button pressed
  • shoot button pressed

Each state needs to check if any relevant events have occurred. Typically this is done with if statements.

But what happen when you are running when you take damage?

The hit by monster event would be triggered and transition the player into the in pain state.

or jumping taking damage and shooting at the same time?

The player would transition into the in pain state again which is where you could display your "hit" sprite that shows the character falling backwards.

You probably aren't going to escape if statements, but you can avoid deeply nested statements.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .