gale.state module
This file contains the implementation of the classes BaseState, StateMachine, HierarchicalState, and StateStack. These classes are used to create a state machine that can change between states.
Author: Alejandro Mujica (aledrums@gmail.com)
- class gale.state.BaseState(state_machine)[source]
Bases:
objectThis class represents an empty state. Any state machines will start in this state.
It also is the base for any state. You should extend this class to implement any new state class.
- Parameters:
state_machine (StateMachine)
- enter(*args, **kwargs)[source]
Method to be executed when the state machine enters in the state.
- Parameters:
args (Tuple[Any])
kwargs (Dict[str, Any])
- Return type:
None
- exit()[source]
Method to be executed when the state machine exits from the state.
- Return type:
None
- class gale.state.StateMachine(states=None)[source]
Bases:
objectThe state machine.
Usage: States are instantiated when they are set to the attribute ‘current’. They are passed to the constructor as a dictionary argument containing pairs either (state_name, StateClass) or (state_name, function_to_build_state).
It is expected that added states contain the methods: enter, exit, update, and render. It is recommended creating states by inheriting from BaseState in base_state module.
Example
- state_machine = StateMachine({
‘start’: StartState, ‘play’: lambda sm: return PlayState(sm)
}) state_machine.change(‘start’)
- Parameters:
states (Dict[str, BaseState] | None)
- change(state_name, *args, **kwargs)[source]
Change the state of the machine.
- Parameters:
state_name (str) – The name of the state that will be set.
args (Tuple[Any])
kwargs (Dict[str, Any])
- Return type:
None
*args and **kwargs: Any argument list of keyword arguments that are accepted by the enter method of the new state.
- Raises:
KeyError – If the arg state_name is not as a key in the states dictionary.
- Parameters:
state_name (str)
args (Tuple[Any])
kwargs (Dict[str, Any])
- Return type:
None
- on_input(input_id, input_data)[source]
Call the method on_input of the current state of the machine.
- Parameters:
input_id (str) – The string that describes the input.
input_data (InputData) – Data associated to the input type.
- Return type:
None
- class gale.state.HierarchicalState(state_machine, substates=None, initial_substate=None)[source]
Bases:
BaseStateA state that owns a nested StateMachine (its “substate machine”).
A HierarchicalState is a regular state from the point of view of the StateMachine (or StateStack) that owns it – it can be added to a ‘states’ dictionary and driven through enter/exit/on_input/update/render just like any other BaseState – but it also behaves as the root of a sub-machine: entering it can select a default substate, and its on_input/update/render delegate down to whichever substate is currently active in that sub-machine.
This is enough to build a hierarchical state machine (HFSM): a “superstate” is simply a HierarchicalState whose substates are BaseState (or, recursively, HierarchicalState) instances. Nesting composes for free: a substate that is itself a HierarchicalState will delegate down to its own substate machine in turn, so arbitrarily deep hierarchies require no extra machinery.
Usage: Subclasses that override enter, on_input, update, or render and still want the substate machine to be driven MUST call the corresponding super().foo(…) method (typically first). Subclasses that do not override these methods inherit the delegation directly, so they nest correctly with no extra code.
Example
- class Walking(BaseState):
- def update(self, dt: float) -> None:
… # move towards the next waypoint
- class LookingAround(BaseState):
- def update(self, dt: float) -> None:
… # rotate in place scanning the surroundings
- class Patrol(HierarchicalState):
- def __init__(self, state_machine: StateMachine) -> None:
- super().__init__(
state_machine, substates={“walking”: Walking, “looking_around”: LookingAround}, initial_substate=”walking”,
)
- def update(self, dt: float) -> None:
super().update(dt) if self.reached_waypoint():
self.change_substate(“looking_around”)
guard_fsm = StateMachine({“patrol”: Patrol, “alert”: Alert}) guard_fsm.change(“patrol”)
- Parameters:
state_machine (StateMachine)
substates (Dict[str, BaseState] | None)
initial_substate (str | None)
- enter(*args, **kwargs)[source]
Select the initial substate, if one was configured, forwarding any received arguments to its enter method.
- Parameters:
kwargs (Dict[str, Any]) – Any argument list or keyword arguments
args (Tuple[Any])
kwargs
- Return type:
None
accepted by the initial substate’s enter method.
- change_substate(state_name, *args, **kwargs)[source]
Change the state of the nested substate machine.
- Parameters:
state_name (str) – The name of the substate that will be set.
kwargs (Dict[str, Any]) – Any argument list or keyword arguments
args (Tuple[Any])
kwargs
- Return type:
None
accepted by the enter method of the new substate.
- Raises:
KeyError – If state_name is not a key in the substates
- Parameters:
state_name (str)
args (Tuple[Any])
kwargs (Dict[str, Any])
- Return type:
None
dictionary.
- on_input(input_id, input_data)[source]
Delegate on_input to the current substate of the substate machine.
- Parameters:
input_id (str) – The string that describes the input.
input_data (InputData) – Data associated to the input type.
- Return type:
None
- class gale.state.StateStack[source]
Bases:
objectClass to stack states. It renders all of then but it only updates the top state.
Usage: The stack is created empty. States are pushed to the stack and popped from it.
state_stack = StateStack() state_stack.push(state1) state_stack.push(state2) state_stack.pop()
- on_input(input_id, input_data)[source]
Call the method on_input of the top state of the stack.
- Parameters:
input_id (str) – The string that describes the input.
input_data (InputData) – Data associated to the input type.
- Return type:
None
- update(dt)[source]
Call to update of the top state of the stack.
- Parameters:
dt (float) – Time elapsed of the game loop.
- Raises:
RuntimeError – If the stack is empty.
- Return type:
None
- render(surface)[source]
Call to render all of the states in the stack.
- Parameters:
surface (Surface) – The surface where the state should be rendered on.
- Return type:
None