A simple pushdown finite states machine library that separates data and behaviors as much as possible.
- States are just enum values.
- Implement behaviors by inheriting from
pdfsm::B
- A state behavior class shouldn't contain any internal data.
- A StateMachine is just a struct, holding active states.
StateMachineHandler
is for handling each state machine's behavior.
-
Defines state enums, there the trailing
N
is necessary:enum class RobotState { Idle, Moving, Dancing, N };
-
Makes a transition table,
jump
s orpush
s that violate this table will throw an exception// for each item: { from, {to list} } pdfsm::TransitionTable<RobotState> transitions{ {RobotState::Idle, {RobotState::Moving, RobotState::Dancing}}, {RobotState::Moving, {RobotState::Idle, RobotState::Dancing}}, {RobotState::Dancing, {RobotState::Idle}}, };
-
Defines a state behavior class for each state:
class RobotMovingBehavior : public pdfsm::B<RobotState::Moving> { public: void OnSetup() override {} void Update(const pdfsm::Context& ctx) override {} void OnEnter(const pdfsm::Context& ctx) override {} void OnTerminate(const pdfsm::Context& ctx) override { } void OnPause(const pdfsm::Context& ctx) override {} void OnResume(const pdfsm::Context& ctx) override {} };
And a behavior table:
pdfsm::BTable<RobotState> behaviors{ std::make_unique<RobotIdleBehavior>(), std::make_unique<RobotMovingBehavior>(), std::make_unique<RobotDancingBehavior>(), };
-
Creates a state machine
fsm
.A
fsm
is just a struct holding active states in a static-array based stack. It can be used as an attribute (or field) of, i.e. a game entity.pdfsm::StateMachine<RobotState> fsm;
-
Makes a context for ticking / update, for propagating to the active state's hook methods:
pdfsm::Context ctx;
-
Creates a handler to manipulate a fsm's state transitions:
pdfsm::StateMachineHandler<RobotState> h(behaviors, transitions);
Before handling a fsm struct, binds it at first:
h.SetHandlingFsm(fsm, ctx);
And then, after handling, clears the binding:
h.ClearHandlingFsm();
-
We can access the handler's pointer inside a state behavior class:
auto& handler = GetHandler(); // returns a pointer to the handler.
-
Operations / APIs of the handler:
// Jump to a state. handler->Jump(ctx, RobotState::Moving); // Push a state and pause current active state. handler->Push(ctx, RobotState::Dancing); // Pop current active state and resume previous paused state. handler->Pop(ctx); // Gets current active state. RobotState state = handler->Top(); // Update (ticking). handler->Update(ctx);
To work with signals, for example, with my tiny signal/event library blinker.h, checkout tests.
BSD.