The pack
debug
function debug(): Pack<{ debug: DebugApi }>
The debug overlay pack. Adds a debug pass after screen and before present, a simulate step that counts
fixed steps, and game.debug. No options: everything is the show() config. Requires a 2D world; draws on
WebGPU or WebGL2, and gathers headless so snapshot() and inspect() stay current.
Types
DebugApi
interface DebugApi
game.debug: the overlay's switch, and the data surface a panel is built on.
show(config?: DebugConfig): void— Switch the overlay on with this config (omitted fields take their defaults). Undone when the scene exits.hide(): void— Switch the overlay off. The profiler rings keep filling.readonly on: boolean— Whether the overlay is drawing (or, headless, gathering).readonly config: Readonly<Required<Omit<DebugConfig, 'toggleKey' | 'pauseKey' | 'exclude' | 'only'>>> & Pick<DebugConfig, 'toggleKey' | 'pauseKey' | 'exclude' | 'only'>— The config in force, defaults filled in.snapshot(): string— The overlay as text: one line per object drawn, then the stats. What a screenshot would show, for a test or a paste.report(key: string, value: string | number): void— Draw calls and whatever else a backend reports, for the stats line. Set by the test bed or a backend; optional.inspect(): Inspect— This frame, in numbers: clock, fps and the three timing rings, scenes, passes, the backend's counts, heap. Cheap; poll it.objects(): ObjectSummary[]— Every live object, one line each.object(id: string): ObjectRecord | null— One object in full: transform, extents, tags, itsdatabag, and every pack's sub-object (body,grid,fsm…) as plain values.set(id: string, path: string, value: unknown): void— Write a field:set('pac-1', 'x', 100),set('ball-3', 'body.vx', 0),set('crab-2', 'data.hp', 9). Throws on an unknown object or path.pause(): void— Pause the clock.resume(): void— Resume the clock.step(n?: number): void— Frame advance: while paused, runnfixed steps on the next frame (default 1). Pauses first if running.
DebugConfig
interface DebugConfig
What show() takes: what to draw, what to leave out, and two optional keys.
bounds?: boolean— The rendered quad of every object (interpolated, rotated, scaled). Default on.hitboxes?: boolean— Collision shapes (collidedata: box or circle) and physics AABBs (body). Default on.touching?: boolean— Sides a physics body is touching, drawn as thick edges. Default on.velocity?: boolean— Velocity arrows:body.vx/vy, or prev→curr for everything else. Default on.ids?: boolean— The object's id above it. Default off (busy).stats?: boolean— The text panel: objects drawn, anything a backendreport()s, the pass order. Default off.profiler?: boolean— The profiler bar along the bottom: fps with min/max, frame / simulate / render ms graphs, JS heap, instances, draw calls, textures. Default on.rays?: boolean— Every raycast made this frame (collision or physics): the ray, its reach, the hit point. Default on.pauseKey?: string— A key that pauses and resumes the clock ('F2'). Default: none.exclude?: ReadonlyArray<string>— Tags or id prefixes to leave out (['wall', 'dot']).only?: ReadonlyArray<string>— Draw only these tags or id prefixes.toggleKey?: string— A key that toggles the overlay ('F1','Backquote'). Default: none.owned?: boolean— Also draw objects a PACK spawned (text glyphs, lights, particles). Default off: they are the pack's business, and a line of text is forty boxes.
Inspect
interface Inspect
One frame in numbers, from inspect().
frame: number— The clock's frame counter.time: number— Simulation time, seconds.paused: boolean— Whether the clock is paused.stepsThisFrame: number— Fixed steps the last frame ran.fps: number— Frames per second, sampled every 500 ms.fpsRange: [number, number]— Min and max fps over the ring.rings: { frame: number[]; sim: number[]; render: number[]; fps: number[] }— Last 120 samples, oldest first: frame, simulate and render time in ms, and fps.objects: number— Live objects in the roster.drawn: number— Objects the overlay drew last frame.rays: number— Raycasts made last frame.scenes: { current: string; stack: string[] }— The current scene and the stack under it.passes: string[]— The frame pass order.backend: { drawCalls: number; instances: number; textures: number; textureBytes: number } | null— The backend's counts from its bag, or null headless.heapMB: number | null— JS heap in MB where the browser reports it, else null.
ObjectRecord
interface ObjectRecord extends ObjectSummary
One object in full: from object(id).
z: number— Depth nudge within the layer.rot: number— Rotation, radians.sx: number— Scale x.sy: number— Scale y.width: number— Unscaled width.height: number— Unscaled height.depth: number— The resolved draw depth.frame: number— The atlas frame index.tint: string— The tint as CSS hex.data: Record<string, unknown>— The object's owndatabag, read into plain values.sub: Record<string, Record<string, unknown>>— Each pack's sub-object, read into plain values (numbers, strings, booleans; nested objects one level).
ObjectSummary
interface ObjectSummary
One object, one line: from objects().
id: string— The object's id.owner: string— Who spawned it: 'game' or a pack id.tags: string[]— Its tags.layer: string— Its draw layer.x: number— Position, world or screen units by layer.y: number— Position, world or screen units by layer.visible: boolean— Whether it draws.packs: string[]— Which pack sub-objects it carries (body, collide, grid, fsm, light, anim).


