Skill: Use dev mode
Gate debug HUDs, cheat keys, verbose logging, and test fixtures on `BT.isDevMode` (engine 1.5.0+) instead of a hand-rolled flag, and expose game state for...
Written for blit386 1.8.0. The rest of blit386.dev documents the newest engine, so an API you find there may be missing from a game pinned to 1.8.0.
BT.isDevMode tells you whether the game is running as a development build or a release build, so you do not have to
invent your own signal for it.
When to use
Use when the user wants a debug HUD, cheat key, verbose console logging, or a test fixture (a level-select shortcut, a god-mode toggle) to work while developing but disappear from a shipped build.
How to do it
update() {
if (BT.isDevMode && BT.isKeyPressed('KeyG')) {
this.godMode = !this.godMode; // dev-only cheat key
}
}
render() {
// ...
if (BT.isDevMode) {
console.log('player', this.player.x, this.player.y); // dev-only verbose logging
}
}BT.isDevMode is a getter (no parentheses) and needs no setup beyond having blit386/vite installed - every scaffold
has it already (see use-hot-reload). It reads true while npm run dev is running the game through that plugin, and
false in a built/shipped game (npm run build).
What dev mode turns on for you (engine 1.7.0+)
Two things come free with a dev build, without any code:
window.BT- the engine puts itself on the page, so you can typeBT.ticks,BT.activeBackend, orBT.palette.get(1)straight into the browser console and inspect the running game. It is not assigned in a built game. Override it either way withbootstrap(Game, { exposeGlobal: true })(orfalse) if you need to.- F9 / Shift+F9 frame capture - F9 copies the current frame to the clipboard, Shift+F9 saves it as a PNG. Turn both
off with
isFrameCaptureShortcutEnabled: falseinconfigure()when your game wants F9 for itself. See thesave-a-screenshotskill.
Left alone, both follow BT.isDevMode, so neither ships to players by accident. Each also has an explicit override that
wins over that default - exposeGlobal: true for the first, isFrameCaptureShortcutEnabled: true for the second - if
you want one in a release build on purpose.
Let an agent read the game's state (engine 1.8.0+)
Add a testState() method to your game class that returns what a play-tester needs to check, as plain JSON:
testState() {
return {
score: this.score,
lives: this.lives,
player: { x: this.player.x, y: this.player.y },
};
}Then, in a dev build, window.BT.testState() in the browser console (or an agent's JavaScript call) returns
{ ticks, backend, state }: the engine's tick counter, the active backend, and a copy of what your method returned.
Read it twice about a second apart and ticks should have grown by about 60.
- Nothing else to wire up: no
window.__game, nodeclare globalblock, noif (BT.isDevMode)around it. It rides onwindow.BT, which only a dev build has. - Keep it plain JSON: numbers, strings, booleans,
null, arrays, and plain objects. The engine copies the result, so aVector2iarrives as{ x, y }and functions orundefinedfields are dropped. - Without the method,
stateisnullandticksandbackendstill work. - If the method throws or returns something JSON cannot hold (an object that contains itself, a
BigInt), the call still returns:stateisnull,errorholds the message, and the browser console shows[BT] testState() threw:. - It keeps working after a hot reload rebuilds the game object - the engine asks the current one every time.
- The engine never calls it on its own, so it costs nothing during play. See
test-the-gamefor using it.
To look at one exact moment instead of a live game, wait until window.BT.isReady is true (init finished, loop exists),
then call await window.BT.renderAt(2.5) - the loop stops on that frame, so window.BT.testState() and
window.BT.captureFrame() both describe tick 150 no matter how slow the agent's tool calls are. window.BT.resume()
lets the game run again.
Notes
BT.isDevModeis tied to the dev server, not toNODE_ENVor any bundler define - there is nothing else to configure.- It answers exactly one question: is this a dev build. It has nothing to do with your own game state (paused, in a menu, level number) - keep those as your own fields.
- The engine gates one thing on this by itself: the BLIT386 splash plays in a release build and not in a dev build. Add
?splashto the URL to see it while developing, or turn it off for good withisSplashEnabled: falseinconfigure(). Seedocs/basics.md(The splash). - This is a convenience for you, the developer, not a security boundary. A player who really wants to could still flip it on in a shipped build; do not rely on it to hide content you actually need to protect.
- Needs blit386
^1.5.0.
Skill: Test the game
Play-test the game in a real browser to check that a change works, reproduce a bug, or see what is on screen. Use whenever you changed gameplay, input,...
Skill: Use hot reload
Keep the game running while editing code or assets with the blit386/vite plugin, optional onHotReload state restore, and in-place sprite/audio/font...