ADR-0004 ยท accepted
One press reaches one step โ
Amended by ADR-0010 on 2026-11-04:
GameLoop.frameruns this step order under either budget,endFrameruns once per frame call that ran a step, andpackages/runtime/src/loop.test.tsnow checks the order and both behaviors.
Amended by ADR-0012 on 2026-11-04: on a lockstep peer, the engine samples the local device source on its own schedule and calls its
endStepandendFrame;GameLoopreads the buffer of merged inputs.
Amended on 2026-11-06:
GameDriveris gone;makeGameEngine'sattachis therequestAnimationFrameadapter, see the note on ADR-0010.
A slow frame runs up to five catch-up steps, and presses used to be reset once per frame, so one press moved push-puzzle's player up to five cells and one undo undid up to five turns (#15, finding 1). GameDriver now calls InputSource.endStep after every step, and endFrame once per frame that ran a step. A source that needs one press to reach one step resets its presses in endStep, as push-puzzle does with InputController.consumePresses().
Considered Options โ
- Call
endFrameafter every step. It was tried in #4 and reverted. It keeps the hook's name and type but changes when it runs, so the compiler can't flag it. Per-frame work in a source would then run up to five times a frame, andInputController.endFramepolls the gamepads. - Make
readreport each press once. Every input source would then have to do this itself, as push-puzzle's first workaround did.
Consequences โ
- For each step the driver calls
read,step, thenendStep.endFramefollows the frame's lastendStep.packages/runtime/src/runtime.test.tschecks this order and both behaviors. - A press made during a frame that runs no step waits for the next step.
- Survivors reads only axes, so it needs no
endStep. - #25 sends each step's input to the other peers. A press lands in exactly one step's input, so every peer applies it once.
endFrameis tied to frames that ran a step. If #25 moves stepping offrequestAnimationFrame(ADR-0003), it has to say whenendFrameruns.