Record a game from its very first frame
game-maker / gate (push) Successful in 4m18s
game-maker / suite (push) Successful in 18m17s

Start recording has to set up its encoders first. It asks the browser
whether it can encode H.264 at the size and hooks in the sound tap,
both asynchronously, and it only took its size at the first frame.
Meanwhile the game ran on unrecorded. A caption that fades in from
alpha 0 at the start was already visible in the first recorded frame.

- A run now waits while a recording sets up its encoders, at most 3 s,
  as it already waits for its videos at Play. That holds in the editor
  and in play.html.
- The recording takes its size at Play, right after the game view has
  the world, rather than at the first frame. A Start recording in
  On start is so ready before the first tick.
- A recording started in the middle of a game holds the picture for
  that moment. A sound that already plays goes on.

Tests:
- tsc, eslint, Prettier clean
- e2e 67 on melektaus-atx: ALL PASSED, 11 checks (67a-ii new). The
  first recorded frame is at game time 0.0168 s, the first frame.
- Without the wait 67a-ii is red: the first recorded frame is at
  0.1667 s, so 10 frames were lost.
- Gate on melektaus-atx: green, 305 files, 4740 tests, run on this
  commit and the one before together.
- Not checked in the browser: a start in the middle of a game, and
  play.html.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-13 10:11:27 +02:00
1 parent 2ba41c1bd0
commit 3443368855
7 files changed
+68 -6

No files matched your search

+22
View File
@@ -62,6 +62,19 @@ export async function recording(t) {
// 67a. Recorded from the start of the run, at 1080p and 30 fps, with the master's sound. The window
// is smaller than 1080p: the frame is drawn into a texture of its own (`PictureReader`).
// The game time is written down each frame until the first frame is taken.
await evaluate(`(() => {
window.__rc67 = { at: null };
const look = () => {
const take = __gm.recording().takes[0];
if (take?.lastFrameAt != null) {
window.__rc67.at = __gm.playInfo().time;
return;
}
requestAnimationFrame(look);
};
requestAnimationFrame(look);
})()`);
await play();
await sleep(1200);
await press('v');
@@ -81,6 +94,15 @@ export async function recording(t) {
JSON.stringify(first),
);
// 67a-ii. The run waits while the recording sets up its encoders: a recording started in
// `On start` has the first frames of the game, not what the game shows a moment later.
const firstAt = await json('window.__rc67.at');
check(
'a recording started in On start takes the first frames of the run',
typeof firstAt === 'number' && firstAt <= 3 / 60,
JSON.stringify({ firstAt }),
);
// 67b. A second start while one records is ignored, and says so in the log.
await press('g');
await sleep(300);