flame_state_machine 2.0.3
flame_state_machine: ^2.0.3 copied to clipboard
A lightweight, type-safe state machine for the Flame game engine, enabling modular and reusable behavior for Flame components.
flame_state_machine #
A lightweight and flexible finite state machine package for the Flame game engine, written in Dart.
Manage complex stateful behaviors for your Flame Components with ease, enabling clean and maintainable game logic.
Features #
- Generic state machine designed to work seamlessly with Flame
Components - Supports prioritized state transitions with custom guard conditions
- Easy registration of reversible transitions
- Lifecycle callbacks for entering, exiting, rendering and updating states
- Support for transitions that can occur from any state
Usage #
1. Create states #
Extend the State<T> class to define your custom states:
class IdleState extends State<Enemy> {
@override
void onEnter(Enemy enemy, [State<Enemy>? from]) {
print('Enemy entered Idle state');
}
@override
void onExit(Enemy enemy, [State<Enemy>? to]) {
print('Enemy exited Idle state');
}
@override
void onRender(Canvas canvas, Enemy enemy) {
// optionally render idle-specific visuals here (useful for debugging)
}
@override
void onUpdate(double dt, Enemy enemy) {
// handle idle behavior
}
}
2. Setup state machine in your Flame component #
Since StateMachine is a Flame Component you can add it directly via the add method of your component
class Enemy extends PositionComponent {
@override
Future<void> onLoad() async {
await super.onLoad();
final idleState = IdleState();
final runningState = RunningState();
final deathState = DeathState();
final stateMachine = StateMachine<Enemy>(
owner: this,
initialState: idleState,
);
// transition from any state with a high priority
stateMachine.register(
to: deathState,
guard: (enemy) => !enemy.isAlive,
priority: 100,
);
stateMachine.register(
from: idleState,
to: runningState,
guard: (enemy) => enemy.isMoving,
reverse: true,
);
// add the state machine as a child component
add(stateMachine);
}
}
Use register() to define valid state changes and their conditions:
stateMachine.register(
priority: 1, // transitions with higher priority values will be checked first
from: IdleState(), // if not provided the transition can occur from any state
to: RunningState(),
guard: (enemy) => enemy.isMoving,
reverse: true, // automatically registers reverse transition
reversePriority: 1, // priority for the reverse transition
reverseGuard: (enemy) => !enemy.isMoving, // guard for the reverse transition (Constructed automatically if not provided)
);
Or use addTransition() to add a StateTransition Object manually:
stateMachine.addTransition(
StateTransition(
from: IdleState(),
to: RunningState(),
guard: (enemy) => enemy.isMoving,
)
);
API #
StateMachine<T>— Core FSM logic, implemented as a FlameComponentState<T>— Base class for your states (overrideonEnter,onExit,onRender,onUpdate)StateTransition<T>— Defines transitions between states with guards and priorities
Contributing #
Contributions and suggestions are welcome! Feel free to open issues or submit pull requests.