Skip to content
/ wisp Public

🔥A godot script for handling state machines quickly

License

Notifications You must be signed in to change notification settings

wyvernbw/wisp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wisp

(sprite from Terraria)

Wisp is a very minimal script (<100 lines) for all your state machine logic:

  • Easy to use: You can create a state machine in a few lines of code
  • Concurrent: You can have multiple state machines running at the same time
  • Minimal: as little overhead as possible and easy to install
  • Full Control: your classes, your code, your game

Install

In your project folder, run:

git submodule add https://github.com/wyvernbw/wisp

If you are using godot 4, run these commands after cloning the repo:

cd wisp # or wherever you cloned the repo
git switch @godot4

done. You can now use the script in your project. Otherwise, you can just copy the script into a new file in your project.

Usage

Get started

Defining States

States are just classes that inherit from Wisp.State.

# Player.gd
class_name Player
extends KinematicBody2D

class IdleState extends Wisp.State:
	func _enter():
		print("Entering Idle State")

or

# IdleState.gd
class_name IdleState
extends Wisp.State

func _enter():
	print("Entering Idle State")

The enter and exit functions are called when transitioning states.

Note that the wisp_process, wisp_physics_process, and wisp_input functions all return a state to transition to. If you want to stay in the same state, return self.

class ExampleState extends Wisp.State:
	func wisp_input(owner: Node, event: InputEvent) -> Wisp.State:
		if event.is_action_pressed("jump"):
			return JumpState.new()
		return self

enter also supports returning a new state. You can also use yield to wait before transitioning. This is useful for states that will always transition to a new state after a certain amount of time. WARNING: returning a new instance of the same class will cause an infinite loop and crash your game! NOTE: before, you could use the 'transition' signal to transition to a new state. While this is still supported, it is recommended to use the return value instead.

class ExampleState extends Wisp.State:
	func enter(owner: Node) -> void:
		# do stuff
		yield(get_tree().create_timer(1), "timeout")
		return JumpState.new()

Creating a state machine

For this, use Wisp.use_state_machine(). This will return a StateMachine object.

func use_state_machine(owner: Node, initial_state: State) -> StateMachine

Example:

onready var state_machine = Wisp.use_state_machine(self, IdleState)

then, in your _process(), _physics_process(), or _input() functions, simply call state_machine.process(), state_machine.physics_process(), or state_machine.input(), respectively.

func _process(delta):
	state_machine.process(delta)

func _physics_process(delta):
	state_machine.physics_process(delta)

func _input(event):
	state_machine.input(event)

Feel free to opt out of calling any of these functions if you don't need to.

API

State

enter

called when entering the state, returns a state to transition to, supports yield

func enter(owner: Node) -> State

exit

called when exiting the state

func exit(owner: Node) -> void

wisp_process

called every frame, returns a state to transition to

func wisp_process(owner: Node, delta: float) -> State

wisp_physics_process

called every physics frame, returns a state to transition to

func wisp_physics_process(owner: Node, delta: float) -> State

wisp_input

called every input event, returns a state to transition to

func wisp_input(owner: Node, event: InputEvent) -> State

Roadmap

  • Basic state logic
  • Concurrency
  • pushdown automata

About

🔥A godot script for handling state machines quickly

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published