Skip to content

Instantly share code, notes, and snippets.

@WolfgangSenff
Created June 3, 2023 11:58
Show Gist options
  • Save WolfgangSenff/469bb278647da5820dfa2550d175c708 to your computer and use it in GitHub Desktop.
Save WolfgangSenff/469bb278647da5820dfa2550d175c708 to your computer and use it in GitHub Desktop.
Pushdown Automata Godot 4.0
extends RefCounted
class_name StateMachine
class PDA:
var stack = []
func push(state):
if stack.size() > 0:
stack[-1].exit(state)
stack.append(state)
state.enter(stack.size() > 1 if stack[stack.size() - 2] != null else null)
Debug.info("Entering state: " + state.get_script().to_string())
func pop():
var prev_state = stack.pop_back()
Debug.info("Leaving state: " + prev_state.get_script().to_string())
prev_state.exit(stack.size() > 0 if stack.back() != null else null)
if stack.size() > 0:
stack.back().enter(prev_state)
return prev_state
func pop_and_push(state):
pop()
push(state)
extends Node
class_name States # Give it a class_name to refer to the states more easily without having to make this a singleton
class State:
var _character # Reference to character
var Gravity = ProjectSettings.get("physics/2d/default_gravity")
func _init(character):
_character = character
func enter(previous_state):
pass
func exit(next_state):
pass
func physics_process(delta):
pass
# Example 1:
class SideIdle extends State:
func enter(previous_state):
_character.state_machine.stack = []
_character.state_machine.stack.append(self)
_character.play_animation("Idle")
_character.velocity.x = 0.0
func physics_process(delta):
if _character.is_moving():
_character.state_machine.push(SideMove.new(_character))
return
if _character.is_jumping():
_character.state_machine.push(SideJump.new(_character))
# Example 2:
class SideFalling extends State:
func enter(previous_state):
_character.play_animation("Fall")
if not _character.state_machine.stack.any(func(state): state is SideJump): # Actually use PDA to check for jump in previous states to prevent coyote jumping if you've jumped already
_character.coyote_timer = _character.coyote_time
... # There's a lot more here, this was just to show the use of the PDA's stack
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment