mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-31 09:49:06 +03:00
79 lines
1.9 KiB
GDScript
79 lines
1.9 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: Node)
|
|
|
|
# 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 var start_state: NodePath
|
|
var states_map := {}
|
|
|
|
var states_stack := []
|
|
var current_state: Node = null
|
|
var _active: bool = false:
|
|
set(value):
|
|
_active = value
|
|
set_active(value)
|
|
|
|
|
|
func _enter_tree() -> void:
|
|
if start_state.is_empty():
|
|
start_state = get_child(0).get_path()
|
|
for child in get_children():
|
|
var err: bool = child.finished.connect(_change_state)
|
|
if err:
|
|
printerr(err)
|
|
initialize(start_state)
|
|
|
|
|
|
func initialize(initial_state: NodePath) -> void:
|
|
_active = true
|
|
states_stack.push_front(get_node(initial_state))
|
|
current_state = states_stack[0]
|
|
current_state.enter()
|
|
|
|
|
|
func set_active(value: bool) -> void:
|
|
set_physics_process(value)
|
|
set_process_input(value)
|
|
if not _active:
|
|
states_stack = []
|
|
current_state = null
|
|
|
|
|
|
func _unhandled_input(input_event: InputEvent) -> void:
|
|
current_state.handle_input(input_event)
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
current_state.update(delta)
|
|
|
|
|
|
func _on_animation_finished(anim_name: String) -> void:
|
|
if not _active:
|
|
return
|
|
|
|
current_state._on_animation_finished(anim_name)
|
|
|
|
|
|
func _change_state(state_name: String) -> void:
|
|
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]
|
|
state_changed.emit(current_state)
|
|
|
|
if state_name != "previous":
|
|
current_state.enter()
|