maniator / maniator/verticopolis
[Discussion] Add debug mode overlay hud flag (to show FPS)
@HongPong is already working on this.
Since Aug 10, 2026.
- Dominant language
- TypeScript
- Stars
- 5
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
When looking into the various things with the graphics it would be good to compare the FPS and other parameters visually. I do not know much about this engine tbh nor existing optimizations. I wanted to throw in these claude notes.
It seemed like kind of a big decision to figure how to implement. But would be helpful to a lot of tasks.
Debug flags
There's no debug flag today, but the pattern is already in the codebase. src/analyticsEnrichment.ts reads ?src=twa via URLSearchParams, and window.game is published in bootstrap.ts:150 with a documented surface that e2e and the screenshot scenes already use.
For right now, before writing anything, this works in the console regardless of your object graph:
(() => { let n = 0, t = performance.now();
const tick = () => { n++; const now = performance.now();
if (now - t >= 1000) { console.log(`fps ${n}`); n = 0; t = now; }
requestAnimationFrame(tick); };
requestAnimationFrame(tick); })();
For something durable, ?debug=fps parses and lets you comma-separate later (?debug=fps,draws):
// src/debugFlags.ts
const raw = new URLSearchParams(window.location.search).get("debug") ?? "";
const flags = new Set(raw.split(",").filter(Boolean));
export const debugEnabled = (f: string): boolean => flags.has(f) || flags.has("all");
Then load the HUD dynamically so it never enters the main bundle:
if (debugEnabled("fps")) void import("./debugHud").then((m) => m.mount(engine));
Two things worth getting right in the HUD itself.
Render it as DOM, not into the canvas. Excalibur's built-in engine.showDebug(true) draws colliders and stats through the same graphics context you're trying to measure, so it adds draw calls to your draw-call count. A position: fixed div updated on Excalibur's postframe event perturbs nothing.
Show draw calls, not just FPS. engine.stats.currFrame carries fps, delta, and a graphics block with drawCalls and drawnImages. drawCalls is the number that answers the batching question from last turn: if it tracks your visible person count, the ten separate person textures are breaking batches and the atlas is worth building. If it stays flat and low, the cost is entity overhead and atlasing buys you nothing.
Add src/debugHud.ts to the coverage-exempt list next to gallery.ts and preview.ts, and to the globIgnores in the PWA config so it stays out of the precache.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.