Documentation
¶
Index ¶
- Constants
- type AnimateEvent
- type AnimationDriver
- type ContinuousEvent
- type DelayedEvent
- type EventQueueManager
- func (eqm *EventQueueManager) HasActiveBackgroundQueues() bool
- func (eqm *EventQueueManager) HasActiveWorkflows() bool
- func (eqm *EventQueueManager) HasBackground(name string) bool
- func (eqm *EventQueueManager) HasFeedback(name string) bool
- func (eqm *EventQueueManager) HasInputBlockingWorkflows() bool
- func (eqm *EventQueueManager) HasOnlyWorkflow(name string) bool
- func (eqm *EventQueueManager) HasWorkflow(name string) bool
- func (eqm *EventQueueManager) RegisterBackgroundQueue(name string) *NamedEventQueue
- func (eqm *EventQueueManager) SetShutdownAction(action func())
- func (eqm *EventQueueManager) ShouldYield(currentPriority int) bool
- func (eqm *EventQueueManager) Shutdown()
- func (eqm *EventQueueManager) TriggerFeedback(name string, priority int, build func(*SequentialEventBuilder))
- func (eqm *EventQueueManager) Update()
- func (eqm *EventQueueManager) UpdateBackground()
- func (eqm *EventQueueManager) UpdateFeedback()
- func (eqm *EventQueueManager) Workflow(name string) *NamedEventQueue
- type EventResult
- type NamedEventQueue
- type Sequence
- type SequentialEventBuilder
- func (seb *SequentialEventBuilder) Animate(durationMs uint64, onFrame func(float32)) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) AwaitFeedback(name string, priority int, build func(*SequentialEventBuilder)) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) BlockInput() *SequentialEventBuilder
- func (seb *SequentialEventBuilder) Finally(action func()) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) First(action func()) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) HandoffTo(newQueueName string, newPriority int, ...) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) If(condition func() bool, build func(*SequentialEventBuilder)) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) RepeatWithDelay(iterations int, delayMs int64, fn func(iteration int) bool) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) RunScript(driver AnimationDriver) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) Start()
- func (seb *SequentialEventBuilder) Then(action func()) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) ThenSequence(sequence Sequence) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) UntilKeyPressed(action func(), intervalMs int64) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) Wait(delayMs int64) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) WaitForAnyKey() *SequentialEventBuilder
- func (seb *SequentialEventBuilder) While(condition func() bool, action func(), intervalMs int64) *SequentialEventBuilder
- func (seb *SequentialEventBuilder) WhileAwaitingInput(action func(), keyCallback func(key *semantic_input.Key) bool, ...) *SequentialEventBuilder
- type SystemCallbacks
Constants ¶
const ( // PriorityCritical - Highest priority, interrupts everything // Use for: Fatal errors, system dialogs, save corruption warnings // Examples: "Game must exit", "Cannot continue", critical system messages PriorityCritical = 1 // PriorityHigh - High priority gameplay events // Use for: Moongate transitions, ship collisions, environmental hazards, combat encounters // Examples: Moongate teleportation, lava damage, earthquake, ship collision // Interrupts: Normal and Low priority queues PriorityHigh = 2 // PriorityMedium - User-initiated interactions // Use for: Player commands (Open, Talk, Search), dialog interactions, NPC conversations // Examples: Dialog workflows, command sequences, conversation trees // Interrupts: Normal and Low priority queues PriorityMedium = 3 // PriorityNormal - Standard gameplay operations // Use for: Sailing, camping, background state updates, routine gameplay // Examples: Automatic sailing, camping sequences, time progression // Interrupted by: Critical, High, Medium priorities PriorityNormal = 5 // PriorityLow - Background effects and animations // Use for: Visual effects, ambient animations, non-critical sound triggers // Examples: Kapow effects, missile animations, background flourishes // Interrupted by: All higher priorities PriorityLow = 10 )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AnimateEvent ¶
type AnimateEvent struct {
DurationMs uint64 // Total animation duration in milliseconds
ElapsedMs uint64 // Time elapsed so far
OnFrame func(progress float32) // Called each frame with progress 0.0-1.0
OnComplete func() // Optional callback when animation completes
}
AnimateEvent provides smooth frame-by-frame animations with progress callbacks
func NewAnimateEvent ¶
func NewAnimateEvent(durationMs uint64, onFrame func(float32)) *AnimateEvent
NewAnimateEvent creates a new animation event
func NewAnimateEventWithCallback ¶
func NewAnimateEventWithCallback(durationMs uint64, onFrame func(float32), onComplete func()) *AnimateEvent
NewAnimateEventWithCallback creates a new animation event with completion callback
func (*AnimateEvent) Execute ¶
func (a *AnimateEvent) Execute(deltaMs uint64) EventResult
Execute updates the animation and calls progress callback each frame
type AnimationDriver ¶
AnimationDriver interface for frame-by-frame animation updates Used by RunScript to drive script executors without circular imports
type ContinuousEvent ¶
type ContinuousEvent interface {
// Execute processes the event and returns whether it should continue
Execute(deltaMs uint64) EventResult
}
ContinuousEvent interface for events that need to run every frame
type DelayedEvent ¶
type DelayedEvent struct {
ExecuteAt int64
Action func() error
// Dynamic chaining support
NextAction func() error // Next action to execute after this one
NextDelay int64 // Delay in ms before executing NextAction
IsWaitPoint bool // True if this event should wait for input before continuing
}
DelayedEvent represents a single delayed action with optional chaining
type EventQueueManager ¶
type EventQueueManager struct {
// contains filtered or unexported fields
}
EventQueueManager manages multiple named event queues
IMPORTANT: Single-threaded Assumption EventQueueManager assumes single-threaded execution in Ebitengine's game loop. Update() is called once per frame on the main thread only. No goroutines access EventQueueManager (web profiling goroutine is isolated). If multi-threaded access is ever needed, add sync.RWMutex protection.
Workflow and feedback queues are serialized independently. Legacy background queues remain concurrent and should not be used for new presentation effects.
func NewEventQueueManager ¶
func NewEventQueueManager(timeSource func() int64, systemCallbacks SystemCallbacks) *EventQueueManager
NewEventQueueManager creates a new event queue manager
func (*EventQueueManager) HasActiveBackgroundQueues ¶
func (eqm *EventQueueManager) HasActiveBackgroundQueues() bool
HasActiveBackgroundQueues returns true if there are any active background queues
func (*EventQueueManager) HasActiveWorkflows ¶
func (eqm *EventQueueManager) HasActiveWorkflows() bool
HasActiveWorkflows reports whether any workflow is active or pending.
func (*EventQueueManager) HasBackground ¶
func (eqm *EventQueueManager) HasBackground(name string) bool
HasBackground reports whether a legacy background queue name is registered.
func (*EventQueueManager) HasFeedback ¶
func (eqm *EventQueueManager) HasFeedback(name string) bool
HasFeedback reports whether feedback is active, pending, deferred, or finalizing.
func (*EventQueueManager) HasInputBlockingWorkflows ¶
func (eqm *EventQueueManager) HasInputBlockingWorkflows() bool
HasInputBlockingWorkflows includes reserved, queued, and finalizing input owners, not just the currently executing workflow.
func (*EventQueueManager) HasOnlyWorkflow ¶
func (eqm *EventQueueManager) HasOnlyWorkflow(name string) bool
HasOnlyWorkflow reports whether name is the sole deferred, active, pending, or finalizing gameplay workflow.
func (*EventQueueManager) HasWorkflow ¶
func (eqm *EventQueueManager) HasWorkflow(name string) bool
HasWorkflow reports whether a workflow is deferred, active, pending, or finalizing.
func (*EventQueueManager) RegisterBackgroundQueue ¶
func (eqm *EventQueueManager) RegisterBackgroundQueue(name string) *NamedEventQueue
RegisterBackgroundQueue creates a background event queue that runs concurrently with the main queue. Background queues are designed for UI-only effects that don't block input or mutate game state.
Key differences from Workflow:
- Never blocks input (isBackground=true)
- Runs in parallel with main queue (not serialized)
- FIFO stacking: multiple background queues execute in order
- Independent lifecycle: continues running even after main queue completes
Use cases: Action feedback popups, visual effects, notifications
Example usage:
eqm.RegisterBackgroundQueue("action_feedback").
Priority(PriorityNormal).
Sequential().
First(func() { dialog.Show() }).
Wait(2000).
Then(func() { dialog.Hide() }).
Start()
func (*EventQueueManager) SetShutdownAction ¶
func (eqm *EventQueueManager) SetShutdownAction(action func())
SetShutdownAction registers owner cleanup for transient state that may outlive an individual queue. It must be configured before shutdown begins.
func (*EventQueueManager) ShouldYield ¶
func (eqm *EventQueueManager) ShouldYield(currentPriority int) bool
ShouldYield checks if a higher priority queue is waiting to execute Returns true if any pending queue has higher priority (lower number) than currentPriority Use in long-running loops (While, WhileAwaitingInput) to cooperatively yield to interruptions
func (*EventQueueManager) Shutdown ¶
func (eqm *EventQueueManager) Shutdown()
Shutdown permanently cancels all scene-owned queues. Every accepted queue runs Finally at most once before input ownership and registrations are released. Repeated shutdowns and later queue starts are harmless.
func (*EventQueueManager) TriggerFeedback ¶
func (eqm *EventQueueManager) TriggerFeedback( name string, priority int, build func(*SequentialEventBuilder), )
TriggerFeedback requests presentation-only feedback and continues without waiting.
func (*EventQueueManager) Update ¶
func (eqm *EventQueueManager) Update()
Update processes the active queue and executes ready events
func (*EventQueueManager) UpdateBackground ¶
func (eqm *EventQueueManager) UpdateBackground()
UpdateBackground processes all background queues concurrently with the main queue. Called from gamescene_update.go after Update() to process visual effects. Background queues never block input and run independently of main queue lifecycle. All active background queues are processed in parallel - each fades independently.
func (*EventQueueManager) UpdateFeedback ¶
func (eqm *EventQueueManager) UpdateFeedback()
UpdateFeedback advances the serialized presentation lane independently of workflows.
func (*EventQueueManager) Workflow ¶
func (eqm *EventQueueManager) Workflow(name string) *NamedEventQueue
Workflow creates an unstarted gameplay workflow. Start atomically reserves its name and safely defers activation when called from another queue callback.
type EventResult ¶
type EventResult int
EventResult represents the result of an event execution
const ( // EventContinue means the event should continue running next frame EventContinue EventResult = iota // EventComplete means the event is finished and should be removed from the queue EventComplete )
type NamedEventQueue ¶
type NamedEventQueue struct {
// contains filtered or unexported fields
}
NamedEventQueue represents an isolated event sequence
func (*NamedEventQueue) Priority ¶
func (neq *NamedEventQueue) Priority(p int) *NamedEventQueue
Priority sets the execution priority for this event queue Lower numbers indicate higher priority (can interrupt lower priority queues) Use constants from priorities.go: PriorityCritical(1), PriorityHigh(2), PriorityMedium(3), PriorityNormal(5), PriorityLow(10) Must be called before Sequential()
func (*NamedEventQueue) Sequential ¶
func (neq *NamedEventQueue) Sequential() *SequentialEventBuilder
Sequential returns a sequential event builder for chained events
type Sequence ¶
type Sequence func(*SequentialEventBuilder) *SequentialEventBuilder
Sequence adds reusable runtime steps to an event sequence.
type SequentialEventBuilder ¶
type SequentialEventBuilder struct {
// contains filtered or unexported fields
}
SequentialEventBuilder builds sequential (chained) event sequences All events use chain mode - legacy pre-calculated timing removed
func (*SequentialEventBuilder) Animate ¶
func (seb *SequentialEventBuilder) Animate(durationMs uint64, onFrame func(float32)) *SequentialEventBuilder
Animate adds a smooth animation event that calls onFrame each frame with progress 0.0-1.0
func (*SequentialEventBuilder) AwaitFeedback ¶
func (seb *SequentialEventBuilder) AwaitFeedback( name string, priority int, build func(*SequentialEventBuilder), ) *SequentialEventBuilder
AwaitFeedback triggers serialized feedback and pauses this sequence until it completes.
func (*SequentialEventBuilder) BlockInput ¶
func (seb *SequentialEventBuilder) BlockInput() *SequentialEventBuilder
BlockInput gives this workflow ownership of the global input block until finalization.
func (*SequentialEventBuilder) Finally ¶
func (seb *SequentialEventBuilder) Finally(action func()) *SequentialEventBuilder
Finally registers guaranteed cleanup that runs exactly once before ownership release. This action is guaranteed to run at the end of the sequence Use for cleanup: hiding dialogs, stopping sounds, clearing state
Example:
g.EventQueueManager.Workflow("camping").
First(func() { dialog.Show() }).
Then(func() { dialog.AppendLine("Healing...") }).
WaitForAnyKey().
Finally(func() {
dialog.Hide() // Cleanup
audio.Stop(sound).Now() // Cleanup
}).
Start()
func (*SequentialEventBuilder) First ¶
func (seb *SequentialEventBuilder) First(action func()) *SequentialEventBuilder
First schedules the first event in a sequential chain
func (*SequentialEventBuilder) HandoffTo ¶
func (seb *SequentialEventBuilder) HandoffTo( newQueueName string, newPriority int, builderFunc func(*SequentialEventBuilder), ) *SequentialEventBuilder
HandoffTo marks the current queue for termination and starts another after cleanup. The current queue's Finally() will run for cleanup, then the chained queue starts via OnComplete Safe to call from inside If()/While() callbacks - termination is deferred until event completes
Use this for internal self-termination with chaining (e.g., sailing → whirlpool transportation) This works for internal conditions where a running queue needs to stop itself and chain to another
Example:
If(func() bool { return landedOnWhirlpool }, func(q *SequentialEventBuilder) {
q.Then(func() { stopSailing() }).
HandoffTo("whirlpool_transport", PriorityHigh, func(wq *SequentialEventBuilder) {
wq.First(func() { showMessage() }).
Then(func() { teleport() })
})
})
func (*SequentialEventBuilder) If ¶
func (seb *SequentialEventBuilder) If( condition func() bool, build func(*SequentialEventBuilder), ) *SequentialEventBuilder
If conditionally executes a block of chained events at runtime. Condition is evaluated at EXECUTION time, not build time, allowing conditions that depend on state set by previous events in the chain.
If condition() returns true when executed, the closure is called to build the sub-chain If condition() returns false, the entire block is skipped
Example:
.If(func() bool { return wandererAppeared }, func(q *SequentialEventBuilder) {
q.Then(func() error { /* wanderer logic */ }).
WaitForAnyKey()
})
func (*SequentialEventBuilder) RepeatWithDelay ¶
func (seb *SequentialEventBuilder) RepeatWithDelay(iterations int, delayMs int64, fn func(iteration int) bool) *SequentialEventBuilder
RepeatWithDelay executes a function N times with a delay between each iteration The function receives the current iteration (0-based) and returns true to continue, false to break early Total duration will be approximately: iterations * delayMs
func (*SequentialEventBuilder) RunScript ¶
func (seb *SequentialEventBuilder) RunScript(driver AnimationDriver) *SequentialEventBuilder
RunScript executes an animation driver until completion. The driver is updated every frame (~16ms) until IsComplete() returns true
This method allows script executors to integrate with the event queue without requiring callback-based completion handling. The script runs inline with normal event queue flow.
Parameters:
- driver: Any AnimationDriver implementation (e.g., minimap.ScriptExecutor)
Example:
executor := minimap.NewScriptExecutor(scene, walkScript)
q.First(func() { /* setup */ }).
RunScript(executor).
Then(func() { /* runs after script completes */ })
func (*SequentialEventBuilder) Start ¶
func (seb *SequentialEventBuilder) Start()
Start executes the sequential event sequence
func (*SequentialEventBuilder) Then ¶
func (seb *SequentialEventBuilder) Then(action func()) *SequentialEventBuilder
Then executes an action immediately after the previous event completes (no delay) The action cannot fail - use RepeatWithDelay if you need error-based early termination If called on an empty queue (no First() yet), automatically becomes First()
func (*SequentialEventBuilder) ThenSequence ¶
func (seb *SequentialEventBuilder) ThenSequence(sequence Sequence) *SequentialEventBuilder
ThenSequence inserts reusable steps when execution reaches this point.
func (*SequentialEventBuilder) UntilKeyPressed ¶
func (seb *SequentialEventBuilder) UntilKeyPressed( action func(), intervalMs int64, ) *SequentialEventBuilder
UntilKeyPressed runs the action repeatedly until any key is pressed This is a convenience wrapper around While() for the common pattern of "run until user input"
Parameters:
- action: Called every iteration (use func() {} for polling without side effects)
- intervalMs: Delay between iterations (e.g., 100ms for smooth movement)
The loop stops when SystemCallbacks.IsAnyKeyPressed() returns true The pressed key is NOT consumed - it will be processed by normal input handlers after the loop exits
Example - Automatic sailing:
.UntilKeyPressed(
func() { moveSailingStep() }, // Called every interval
100, // 100ms between moves
)
func (*SequentialEventBuilder) Wait ¶
func (seb *SequentialEventBuilder) Wait(delayMs int64) *SequentialEventBuilder
Wait pauses for the specified duration without executing any action
func (*SequentialEventBuilder) WaitForAnyKey ¶
func (seb *SequentialEventBuilder) WaitForAnyKey() *SequentialEventBuilder
WaitForAnyKey pauses the event sequence until any key is pressed
func (*SequentialEventBuilder) While ¶
func (seb *SequentialEventBuilder) While( condition func() bool, action func(), intervalMs int64, ) *SequentialEventBuilder
func (*SequentialEventBuilder) WhileAwaitingInput ¶
func (seb *SequentialEventBuilder) WhileAwaitingInput( action func(), keyCallback func(key *semantic_input.Key) bool, intervalMs int64, ) *SequentialEventBuilder
WhileAwaitingInput runs the action repeatedly, checking for key input after each iteration This is similar to UntilKeyPressed but provides the specific key to the callback for decision-making
Parameters:
- action: Called every iteration before key check (use func() {} for polling without side effects)
- keyCallback: Called with the currently pressed key (or nil if no key pressed) Returns true to stop loop, false to continue
- intervalMs: Delay between iterations (e.g., 100ms for smooth movement)
The callback receives *semantic_input.Key which can be:
- nil: No key currently pressed
- Arrow key: Same direction (continue sailing) or different direction (change sailing direction)
- Space bar: Stop sailing with "Sheets in irons!" message
- Any other key: Stop loop AND process key as normal command (not consumed)
Example - Automatic sailing with direction changes:
.WhileAwaitingInput(
func() { moveSailingStep() }, // Called every interval
func(key *semantic_input.Key) bool {
if key == nil { return false } // No key - continue
if *key == semantic_input.KeySpace { return true } // Space - stop
if isArrowKey(key) {
changeSailingDirection(key) // Arrow - change direction
return false // Continue sailing
}
return true // Other key - stop and process
},
100, // 100ms between moves
)
type SystemCallbacks ¶
type SystemCallbacks interface {
BlockAllInput(block bool)
IsAnyKeyPressed() bool
GetPressedKey() *semantic_input.Key
}
SystemCallbacks interface for input management