stage — Luau Binding

require("stage"): the substrate the animation family shares — create targets, subscribe to the event bus, and drive the tick. The programmatic surface of the stage. Every function is [antos].

Status: design. Not built yet. Signatures are the intended surface, settled against the stage model.

local stage = require("stage")

Targets

The shared registry motion / tween / collision all read and write. A target created here is seen by every sibling.

Call Returns Does
stage.target(kind, id?, opts?) target create or fetch a target — "turtle", "sprite" (with id), or a custom { x, y, heading, … }. Carries position, properties, and a collision bound. The siblings' own *.target helpers reach this same registry
stage.targets() list every registered target
stage.remove(target) ok drop a target, stopping anything running on it

Events

The bus the siblings emit onto and scripts subscribe to — delivered in the React phase.

Call Returns Does
stage.on(event, handler) sub subscribe to an event ("collision:enter", a custom name, …); handler(...) runs in React. Returns a handle
stage.off(sub) ok unsubscribe
stage.emit(event, ...) — raise a custom event — queued and delivered in React like any other, so a script's own events keep the deterministic order

The tick

Normally the OS runs the tick; these step it — for headless tests, a paused debugger, a deterministic replay.

Call Returns Does
stage.tick(n?) now advance the simulation n ticks (default 1), running the full phase order each. The lever that makes a scene replayable: same start state + same tick count = same result
stage.now() number the current tick count
stage.pause() / stage.resume() ok halt / continue the OS-driven tick
-- a deterministic headless test: set up, step, assert
local stage  = require("stage")
local motion = require("motion")
local t = stage.target("sprite", 1)
motion.play(t, "FD 100")
stage.tick(60)                       -- advance 60 ticks, no display needed
assert(t.x == 100)                   -- exact, every run

Randomness

One deterministic stream every system shares — never math.random (see determinism-safe randomness).

Call Returns Does
stage.random(a?, b?) number the next value from the stage's PRNG — [0,1) bare, an integer in [1,a] or [a,b] with args. What particles, a physics scatter, or a random spawn must use
stage.seed(s?) number set the run seed (a reproducible run); with no argument, seed once and return the seed used, so a good run can be replayed

Snapshot and restore

Save and restore the whole simulation state at a tick — the target registry, the PRNG, and every sibling's state. The capability net-sync rollback needs, and a clean basis for undo and deterministic replay.

Call Returns Does
stage.snapshot() snap capture the entire sim state at the current tick
stage.restore(snap) ok restore the sim to a captured state, then re-simulate forward deterministically with stage.tick

Where to go next

Important: The Ant64 family of home computers are at early design/prototype stage, everything you see here is subject to change.