game skeleton
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
// Package world is the domain aggregate: a thin layer around the inkwell Game
|
||||
// holding the runtime state that must NOT be saved, plus the game's own
|
||||
// actions and the action pump.
|
||||
//
|
||||
// This package knows nothing about the HUD or the content, so ui and content
|
||||
// can both build on it without creating an import cycle.
|
||||
package world
|
||||
|
||||
import (
|
||||
inkwell "git.teletypegames.org/engines/inkwell"
|
||||
|
||||
"realworld/internal/names"
|
||||
)
|
||||
|
||||
// Mode is the HUD mode.
|
||||
//
|
||||
// IMPORTANT: this is deliberately NOT a State.Var. inkwell's state.save.go
|
||||
// serialises State.Vars but drops the in-flight script ("saves capture state at
|
||||
// idle/ready boundaries"), so a save taken mid-cutscene would reload into a
|
||||
// permanently letterboxed, HUD-less game with no script running. The mode is
|
||||
// therefore an unsaved runtime field.
|
||||
type Mode string
|
||||
|
||||
const (
|
||||
ModePlay Mode = "play" // full HUD
|
||||
ModeCutscene Mode = "cutscene" // letterbox, HUD hidden
|
||||
ModeMenu Mode = "menu" // main menu, HUD hidden
|
||||
)
|
||||
|
||||
// World holds the runtime state that does not belong in a save file.
|
||||
type World struct {
|
||||
G *inkwell.Game
|
||||
|
||||
mode Mode
|
||||
|
||||
scene string // current scene — inkwell exposes no accessor for it
|
||||
paused bool // is the world stopped (during dialogue), for the TopBar suffix
|
||||
pending string // the tape currently being loaded into slot 2
|
||||
queue []inkwell.Action // HUD-originated actions waiting to run
|
||||
running inkwell.Runner
|
||||
top *inkwell.TopBar // the location bar, so the pump can write its suffix
|
||||
|
||||
// During a cutscene a tape signals but never interrupts: the line waits
|
||||
// here until the player asks for it with SPACE.
|
||||
tapeWaiting bool
|
||||
tapeLine inkwell.Action
|
||||
}
|
||||
|
||||
// New wraps an existing inkwell game.
|
||||
func New(g *inkwell.Game) *World {
|
||||
return &World{G: g, mode: ModePlay}
|
||||
}
|
||||
|
||||
// Mode returns the current HUD mode.
|
||||
func (w *World) Mode() Mode { return w.mode }
|
||||
|
||||
// SetMode switches the HUD mode.
|
||||
func (w *World) SetMode(m Mode) { w.mode = m }
|
||||
|
||||
// HUDVisible reports whether the HUD should draw: only in play mode.
|
||||
func (w *World) HUDVisible() bool { return w.mode == ModePlay }
|
||||
|
||||
// Scene returns the name of the current scene.
|
||||
func (w *World) Scene() string { return w.scene }
|
||||
|
||||
// Paused reports whether the world is stopped (during dialogue).
|
||||
func (w *World) Paused() bool { return w.paused }
|
||||
|
||||
// SetTopBar hands over the location bar so the pump can write its suffix.
|
||||
func (w *World) SetTopBar(t *inkwell.TopBar) { w.top = t }
|
||||
|
||||
// Slot2 returns the item name in the second tape slot, empty if there is none.
|
||||
//
|
||||
// Unlike Mode, this is REAL game state and lives in State.Var so that it is
|
||||
// saved.
|
||||
func (w *World) Slot2() string {
|
||||
if v, ok := w.G.State.Var(names.VarSlot2).(string); ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetSlot2 sets the contents of the second tape slot.
|
||||
func (w *World) SetSlot2(item string) { w.G.State.SetVar(names.VarSlot2, item) }
|
||||
|
||||
// SetPending marks which tape is going into slot 2. The tape-insert script
|
||||
// performs the actual load; the widget only marks.
|
||||
func (w *World) SetPending(item string) { w.pending = item }
|
||||
|
||||
// TakePending returns and clears the tape waiting to be loaded.
|
||||
func (w *World) TakePending() string {
|
||||
item := w.pending
|
||||
w.pending = ""
|
||||
return item
|
||||
}
|
||||
|
||||
// TapeWaiting reports whether a tape line has been offered but not yet spoken.
|
||||
func (w *World) TapeWaiting() bool { return w.tapeWaiting }
|
||||
Reference in New Issue
Block a user