fsm

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package fsm provides flat (single-level) finite state machines for components that need explicit, transition-bounded behavior. Use when a component's behavior changes by mode — Player has Idle/Walk/Dash/Hurt; Enemy has Patrol/Chase/Attack/Dead — and you want the transitions to be auditable rather than implicit in scattered if-statements.

Lifetime is owner-bound: an FSM lives as long as its owner node is in the tree. When the owner exits the tree, the FSM stops dispatching callbacks. There is no separate "stop" call.

Example:

const (
    Idle = "idle"
    Walk = "walk"
    Dash = "dash"
)

func (p *Player) Ready() {
    p.mode = fsm.New(p.AsNode(), Idle).
        On(Idle).
            Enter(func() { p.SetVelocity(gogogd.Vec2{}) }).
            Update(func(dt gogogd.Delta) {
                if gogogd.ActionJustPressed("dash") {
                    p.mode.Goto(Dash)
                }
            }).
        On(Dash).
            Enter(func() { p.dashTime = 0.2 }).
            Update(func(dt gogogd.Delta) {
                p.dashTime -= dt
                if p.dashTime <= 0 { p.mode.Goto(Idle) }
            }).
        Done()
}

func (p *Player) Process(dt gogogd.Delta) { p.mode.Tick(dt) }

The machine fires Enter / Exit / Update callbacks for the current state only. Calling Goto inside Update is safe — the transition is queued and applied at the end of the Update call.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder is the chainable configuration handle returned by New. Each On(state) call selects the state being configured; subsequent Enter/Exit/ Update calls bind callbacks to it. Done finalizes and returns the live Machine.

func New

func New(owner Node.Instance, initial string) *Builder

New constructs a machine owned by node, starting in the given initial state. The machine auto-dies when owner exits the tree.

Pass to a Builder via the chainable On / Enter / Exit / Update API:

m := fsm.New(p.AsNode(), "idle").
    On("idle").Enter(...).Update(...).
    On("walk").Enter(...).Update(...).
    Done()

func (*Builder) Done

func (b *Builder) Done() *Machine

Done finalizes configuration and returns the live machine. Fires the Enter callback for the initial state once.

func (*Builder) Enter

func (b *Builder) Enter(fn func()) *Builder

Enter registers fn to run when the machine transitions *into* the currently-selected state.

func (*Builder) Exit

func (b *Builder) Exit(fn func()) *Builder

Exit registers fn to run when the machine transitions *out of* the currently-selected state.

func (*Builder) Guard

func (b *Builder) Guard(target string, guard func() bool) *Builder

Guard registers a predicate gating transitions from the currently-selected state to target. The transition is denied (silently) if guard returns false. Use sparingly — most "can I dash?" checks belong in the caller of Goto, not in a guard table.

.On("idle").Guard("dash", func() bool { return p.stamina > 10 })

func (*Builder) On

func (b *Builder) On(state string) *Builder

On selects state for subsequent configuration calls. Calling On with a previously-seen state name reopens it for additional configuration.

func (*Builder) Update

func (b *Builder) Update(fn func(Delta)) *Builder

Update registers fn to run each Tick while the machine is in the currently-selected state.

type Delta

type Delta = float32

Delta mirrors gogogd.Delta — the time-step type Godot passes to Process. Duplicated here to avoid an fsm → gogogd import cycle.

type Machine

type Machine struct {
	// contains filtered or unexported fields
}

Machine is the runtime state of a finite state machine. Construct with New and configure via the chainable Builder API. The Machine's methods (Goto / Tick / Current) are safe to call from any code with a reference; transitions are processed synchronously inside Tick.

func (*Machine) Current

func (m *Machine) Current() string

Current returns the active state name.

func (*Machine) Goto

func (m *Machine) Goto(state string)

Goto requests a transition to state. The transition runs immediately unless called from within an Update callback, in which case it's queued and applied at the end of that Tick.

Denied (silently) if a Guard registered for current → state returns false, or if the machine's owner has left the tree.

func (*Machine) Tick

func (m *Machine) Tick(dt Delta)

Tick advances the machine by dt. Call from your component's Process or PhysicsProcess. Safe when the owner is out-of-tree (no-op).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL