State Machines

MV3D provides a state machine class, which is located in mv3d.util.statemachine. To learn what a Finite State Machine is, see the Wikipedia article. State machines can be very useful is games. MV3D uses a state machine on the client to handle changing between login screens and in game. There are two main parts to the state machine: the state machine object itself, and individual states. Both of these are represented by Python classes that can be inherited from.

State Machine Class

The StateMachine class is the top level of the state machine. Unlike some other implementations of state machines, it does not know all of its possible states ahead of time. It only knows its current state. The StateMachine can send messages to the current state using the handleEvent method. It can also be used to schedule an event to go off in the future with scheduleEvent. Finally, it handles changing states with changeState. Generally, you'll want to subclass this for your own use, but that isn't strictly necessary.

States

Each state for the StateMachine is its own class. To do anything useful with a state, it is required to subclass the State class. A State consists of a normal Python __init__ (be sure to call the State.__init___ from the subclass). This is where any code that is to be executed when the state is entered goes. There's a getWeight and getDesire class method which return a number to inform the StateMachine of the weighting to enter the state when multiple states are passed in to changeState.

States can handle events as well. These can either be immediate or scheduled events. To handle an event, define a new method in the state called event_XX} where XX is the name of the event. Then to send that event, call handleEvent("XX", *args, **kwargs on the StateMachine. An additional positional arg at the beginning of the args will be added which is a reference to the state machine. To prevent circular references, it's a good idea not to cache a reference to the state machine inside of a state.

Note that changing state within a state machine is valid, however, currently if doing so within the __init__, unexpected results may occur. It is better to schedule an event to change states in this case.