1
0
Fork 0

feat: add basic state machine implementation

This commit is contained in:
Henrik Hautakoski 2025-09-21 12:15:17 +02:00
parent ceb4cfad40
commit 75b4981566
3 changed files with 82 additions and 0 deletions

8
game/state/handler.go Normal file
View file

@ -0,0 +1,8 @@
package state
type Handler interface {
Enter()
Exit()
Update(transitioner Transitioner, delta float32)
Render()
}

View file

@ -0,0 +1,68 @@
package machine
import "tetris/game/state"
type Machine struct {
current state.Handler
pending string
registry map[string]state.Handler
}
// New creates an empty machine.
func New() *Machine {
return &Machine{registry: make(map[string]state.Handler)}
}
// Register binds a name to a factory that returns a fresh state.Handler.
func (m *Machine) Register(name string, handler state.Handler) {
m.registry[name] = handler
}
// Start switches to the named initial state immediately (calls Enter()).
func (m *Machine) Start(name string) {
m.switchNow(name)
}
// Switch queues a transition to be applied after the current Update finishes.
func (m *Machine) Switch(name string) {
if name == "" || name == m.pending {
return
}
m.pending = name
}
// Update ticks the current state, then applies any queued transition.
func (m *Machine) Update(delta float32) {
if m.current == nil {
return
}
m.current.Update(m, delta)
if m.pending != "" {
next := m.pending
m.pending = ""
m.switchNow(next)
}
}
// Render proxies to current state.
func (m *Machine) Render() {
if m.current != nil {
m.current.Render()
}
}
func (m *Machine) switchNow(name string) {
handler, ok := m.registry[name]
if !ok {
// Unknown state: dont switch.
return
}
if m.current != nil {
m.current.Exit()
}
m.current = handler
m.current.Enter()
}

View file

@ -0,0 +1,6 @@
package state
// Transitioner is the only thing a state needs to know about the machine.
type Transitioner interface {
Switch(name string) // request transition by state name
}