state_machine.gd 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. """
  2. Base interface for a generic state machine
  3. It handles initializing, setting the machine active or not
  4. delegating _physics_process, _input calls to the State nodes,
  5. and changing the current/active state.
  6. See the PlayerV2 scene for an example on how to use it
  7. """
  8. extends Node
  9. signal state_changed(current_state)
  10. """
  11. You must set a starting node from the inspector or on
  12. the node that inherits from this state machine interface
  13. If you don't the game will crash (on purpose, so you won't
  14. forget to initialize the state machine)
  15. """
  16. export(NodePath) var START_STATE
  17. var states_map = {}
  18. var states_stack = []
  19. var current_state = null
  20. var _active = false setget set_active
  21. func _ready():
  22. if not START_STATE:
  23. START_STATE = get_child(0).get_path()
  24. for child in get_children():
  25. child.connect("finished", self, "_change_state")
  26. initialize(START_STATE)
  27. func initialize(start_state):
  28. set_active(true)
  29. states_stack.push_front(get_node(start_state))
  30. current_state = states_stack[0]
  31. current_state.enter()
  32. func set_active(value):
  33. _active = value
  34. set_physics_process(value)
  35. set_process_input(value)
  36. if not _active:
  37. states_stack = []
  38. current_state = null
  39. func _input(event):
  40. current_state.handle_input(event)
  41. func _physics_process(delta):
  42. current_state.update(delta)
  43. func _on_animation_finished(anim_name):
  44. if not _active:
  45. return
  46. current_state._on_animation_finished(anim_name)
  47. func _change_state(state_name):
  48. if not _active:
  49. return
  50. current_state.exit()
  51. if state_name == "previous":
  52. states_stack.pop_front()
  53. else:
  54. states_stack[0] = states_map[state_name]
  55. current_state = states_stack[0]
  56. emit_signal("state_changed", current_state)
  57. if state_name != "previous":
  58. current_state.enter()