summaryrefslogtreecommitdiff
path: root/godot/scripts/fsm
diff options
context:
space:
mode:
Diffstat (limited to 'godot/scripts/fsm')
-rw-r--r--godot/scripts/fsm/State.gd22
-rw-r--r--godot/scripts/fsm/StateMachine.gd35
2 files changed, 57 insertions, 0 deletions
diff --git a/godot/scripts/fsm/State.gd b/godot/scripts/fsm/State.gd
new file mode 100644
index 0000000..be7ba2d
--- /dev/null
+++ b/godot/scripts/fsm/State.gd
@@ -0,0 +1,22 @@
+class_name State
+extends Node
+
+var state_machine = null
+
+# Corresponds to the `_process()` callback.
+func update(_delta: float) -> void:
+ pass
+
+# Virtual function. Corresponds to the `_physics_process()` callback.
+func physics_update(_delta: float) -> void:
+ pass
+
+# Virtual function. Called by the state machine upon changing the active state. The `msg` parameter
+# is a dictionary with arbitrary data the state can use to initialize itself.
+func enter(_msg := {}) -> void:
+ pass
+
+# Virtual function. Called by the state machine before changing the active state. Use this function
+# to clean up the state.
+func exit() -> void:
+ pass
diff --git a/godot/scripts/fsm/StateMachine.gd b/godot/scripts/fsm/StateMachine.gd
new file mode 100644
index 0000000..834f036
--- /dev/null
+++ b/godot/scripts/fsm/StateMachine.gd
@@ -0,0 +1,35 @@
+class_name StateMachine
+extends Node
+
+# Emitted when transitioning to a new state.
+signal transitioned(state_name)
+
+# Path to the initial active state. We export it to be able to pick the initial state in the inspector.
+export var initial_state := NodePath()
+
+# The current active state. At the start of the game, we get the `initial_state`.
+onready var state: State = get_node(initial_state)
+
+
+func _ready() -> void:
+ yield(owner, "ready")
+ # The state machine assigns itself to the State objects' state_machine property.
+ for child in get_children():
+ child.state_machine = self
+ state.enter()
+
+func _process(delta: float) -> void:
+ state.update(delta)
+
+func _physics_process(delta: float) -> void:
+ state.physics_update(delta)
+
+func transition_to(target_state_name: String, msg: Dictionary = {}) -> void:
+ if not has_node(target_state_name):
+ print("no state")
+ return
+
+ state.exit()
+ state = get_node(target_state_name)
+ state.enter(msg)
+ emit_signal("transitioned", state.name)