Show the frame rate the measured times allow in the overlay (#275)
game-maker / gate (push) Successful in 2m35s
game-maker / suite (push) Successful in 11m46s

The fps line of the performance overlay stops at the display's rate,
60 on most screens. It does not tell how much room a game has left.
The new top line answers that from the times the overlay measures.

- possibleFps in src/editor/frameMeter.ts is 1000 ms over the sum of
  the five areas, rounded down. It has no number while nothing took
  any time, and the overlay shows a dash then.
- The editor's share is in the sum, because it costs time while
  playing in the editor. A released game can do a little better.
- It is an upper bound. The GPU's time is not measured and not in it.
- e2e 59e reads the lines one further down and checks the new line
  against the times it measured itself.

Tests:
- Unit frame-meter: 11 passed (+2 for possibleFps)
- Gate: 197 files, 2855 tests, CHECK EXIT 0 (2853 + 2)
- e2e 59: ALL PASSED, 19 checks (+1), on melektaus-atx
- Counter-check: possibleFps without the editor's share fails the
  unit test
- The e2e total of 1602 is counted (1601 + 1), not measured

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-09-30 11:18:39 +02:00
1 parent 77f4c2c1a3
commit f14c4ecb77
4 files changed
+43 -8

No files matched your search

+13 -6
View File
@@ -142,7 +142,8 @@ export async function whilePlaying(t) {
);
// 59e. The performance overlay (#275): switched on in the game tab's header, it shows over a
// running game only, top left – fps, the entities the world has, and a time per area.
// running game only, top left – the fps the times allow, fps, the entities the world has,
// and a time per area.
const performance = () => json('__gm.gamePerformance()');
await showTab('game');
await click((await performance()).button.x, (await performance()).button.y);
@@ -171,19 +172,25 @@ export async function whilePlaying(t) {
);
check(
'it counts the entities the running world has',
measured?.entities === running.entities && overlay.lines[0]?.includes(`· ${running.entities} entities`),
JSON.stringify({ measured, entities: running.entities, line: overlay.lines[0] }),
measured?.entities === running.entities && overlay.lines[1]?.includes(`· ${running.entities} entities`),
JSON.stringify({ measured, entities: running.entities, line: overlay.lines[1] }),
);
check(
'and shows the fps and a time for each of the five areas, drawing included',
/^\d+ fps/.test(overlay.lines[0] ?? '') &&
overlay.lines.length === 6 &&
overlay.lines.slice(1).every((line) => / \d+\.\d\d ms$/.test(line)) &&
/^\d+ fps/.test(overlay.lines[1] ?? '') &&
overlay.lines.length === 7 &&
overlay.lines.slice(2).every((line) => / \d+\.\d\d ms$/.test(line)) &&
times.length === 5 &&
times.every((ms) => Number.isFinite(ms) && ms >= 0) &&
measured.times.drawing > 0,
JSON.stringify(overlay.lines),
);
const possible = Math.floor(1000 / times.reduce((sum, ms) => sum + ms, 0));
check(
'on top it shows the fps the measured times would allow, a second over their sum',
new RegExp(`^Possible +${possible} fps$`).test(overlay.lines[0] ?? '') && possible > 0,
JSON.stringify({ line: overlay.lines[0], possible }),
);
await shot('59c-performance');
await click(overlay.button.x, overlay.button.y);
const switchedOff = await performance();