Sampled, not stepped
Three unrelated parts of Orblit share one design, and it’s worth naming, because it explains a good deal of the API.
An effect, a sprite animation and a cutscene are all functions of a playhead. You don’t advance them. You ask them for a moment.
final pose = effect.at(1.4); // not effect.step(dt)final frame = animation.at(1.4);final world = sequence.at(1.4);Why not step
Section titled “Why not step”The obvious design is step(dt), where each thing keeps its own accumulated
time and you nudge it forwards every frame. It’s simpler to write, and it’s
wrong in four ways that matter.
Scrubbing. Dragging a cutscene’s playhead backwards means either stepping
with a negative dt, which most step functions handle badly or not at all, or
replaying from the start. Sampling just asks for the moment.
Replay. A stepped system’s state depends on the sequence of frames it received, so a replay at a different frame rate is a different replay. A sampled system gives the same answer for the same moment, always.
Drift. Accumulating dt accumulates floating-point error. After ten
minutes, two stepped animations that started together have quietly come apart.
Joining late. A day cycle that began four minutes ago isn’t something a newly arrived viewer should have to pick up from the middle. With sampling they don’t have to: they’re shown the moment, not the history that led to it.
What it makes possible
Section titled “What it makes possible”The network’s interpolation. Multiplayer receives acknowledged deltas at whatever rate they arrive and needs a value for now, between two of them. Sampling is the whole mechanism.
The sequencer. A cutscene is tracks of clips over a playhead. Sampling it at any moment gives you the whole world’s worth of values, which is why scrubbing, replaying and stepping backwards all come out the same as playing forwards.
Testing. Assert what the effect looks like at 1.4 seconds. No loop, no fake clock, no frame count.
Where you still step
Section titled “Where you still step”The simulation does step, because physics really is an integrator: where a
body is at t depends on where it went to get there. So does a behaviour
tree, because a decision made last tick is meant to persist.
The distinction is whether a thing has history, or only a value at a time. Animation, effects and cutscenes are the second kind, and the API says so.
