12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- 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 var start_state: NodePath
- var states_map = {}
- var states_stack = []
- var current_state = null
- var _active = false:
- set(value):
- _active = value
- set_active(value)
- func _enter_tree():
- if start_state.is_empty():
- start_state = get_child(0).get_path()
- for child in get_children():
- var err = child.finished.connect(self._change_state)
- if err:
- printerr(err)
- initialize(start_state)
- func initialize(initial_state):
- _active = true
- states_stack.push_front(get_node(initial_state))
- current_state = states_stack[0]
- current_state.enter()
- func set_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()
|