Files
godot-demo-projects/2d/finite_state_machine/state_machine/state_machine.gd
Aaron Franke 006309bd6f Many tweaks thanks to IAmActuallyCthulhu
Also change apostrophes to double quotes and update C# projects
2020-06-28 13:19:13 -04:00

75 lines
1.7 KiB
GDScript

extends Node
# Base interface for a generic state machine.
# It handles initializing, setting the machine active or not
# delegating _physics_process, _input calls to the State nodes,
# and changing the current/active state.
# See the PlayerV2 scene for an example on how to use it.
signal state_changed(current_state)
# You should set a starting node from the inspector or on the node that inherits
# from this state machine interface. If you don't, the game will default to
# the first state in the state machine's children.
export(NodePath) var start_state
var states_map = {}
var states_stack = []
var current_state = null
var _active = false setget set_active
func _ready():
if not start_state:
start_state = get_child(0).get_path()
for child in get_children():
var err = child.connect("finished", self, "_change_state")
if err:
printerr(err)
initialize(start_state)
func initialize(initial_state):
set_active(true)
states_stack.push_front(get_node(initial_state))
current_state = states_stack[0]
current_state.enter()
func set_active(value):
_active = value
set_physics_process(value)
set_process_input(value)
if not _active:
states_stack = []
current_state = null
func _unhandled_input(event):
current_state.handle_input(event)
func _physics_process(delta):
current_state.update(delta)
func _on_animation_finished(anim_name):
if not _active:
return
current_state._on_animation_finished(anim_name)
func _change_state(state_name):
if not _active:
return
current_state.exit()
if state_name == "previous":
states_stack.pop_front()
else:
states_stack[0] = states_map[state_name]
current_state = states_stack[0]
emit_signal("state_changed", current_state)
if state_name != "previous":
current_state.enter()