Developing with crisp-game-lib
Workflow
- Inspect the existing project before choosing a setup. Preserve its pinned library version, entry style, helpers, and test harness.
- For a new project, choose CDN/classic-script or npm/bundler setup. Read project-setup-and-modes.md before creating entry files or selecting a version.
- State each named action and its physical bindings before coding. For a one-button game, state whether press, hold, or release acts and which phases are intentionally unused.
- Implement one clear frame order: input → state/physics → spawning → drawing/collision → scoring → game over.
- Apply the runtime contracts below and validate only behavior the change can reach. A new game or entry-point/input/audio/loop change needs a real-browser runtime check; a localized fix needs the affected check plus startup smoke.
- After the first working loop, record any interesting emergent behavior before deciding whether a collision artifact, draw-order effect, or physics interaction is a bug or a better mechanic.
Use if (!ticks) { ... } for first-frame initialization in classic-script projects. In a bundler project, follow the existing init({ update, title, description, characters, options }) entry style.
Runtime contracts
- Use documented APIs only. Test mocks may expose globals absent from the browser bundle. Consult api.md for exact signatures, colors, sounds, collision properties, and options; use standard JavaScript or define any missing helper yourself.
- Drawing order is collision order. A shape detects only shapes drawn earlier in the same frame. Draw targets first and detectors second.
- Treat
input.isJustPressed as unified input. It merges keyboard keys and pointer input. Use keyboard.code[...] for a named keyboard action and pointer.isJustPressed for pointer-only input. Unified input is appropriate for “any input starts.”
- Define bindings once per named action. Every phase must read the same synonym set. Multiple physical keys bound to one named action do not create additional game actions.
- Keep library-owned and game-owned arcade cycles separate. The normal cycle uses
title, description, library score rendering, and end(). A custom attract/ceremony/name-entry cycle owns all of those. Read project-setup-and-modes.md before implementing or changing a custom cycle.
- Verify audio audibly. For built-in audio on crisp-game-lib 1.5.0+, load both algo-chip globals before the bundle and verify
algoChipSession != null after first input. Missing globals silently disable play() and BGM.
- Use current particle syntax. Call
particle(pos, { count, speed, angle, angleWidth }); do not introduce the legacy positional form.
- Avoid
white for visible art. It matches the background across bundled themes. Use another color or a light_* variant.
Minimal collision pattern:
color("red");
enemies.forEach((enemy) => box(enemy.pos, 10));
color("blue");
if (box(player.pos, 8).isColliding.rect.red) {
end();
}
Conditional references
- Read api.md whenever exact library behavior matters. Its API enumeration is canonical; do not reconstruct it from memory.
- Read examples.md only when a complete loop matching the requested control or game pattern would reduce implementation risk.
- Read project-setup-and-modes.md for CDN/npm skeletons, version pinning, default input bindings, custom arcade ownership, or this repository's simulator/tester constraints.
Validation
Check the applicable items in a real browser:
- startup has no console error or uncaught exception;
- controls map only to their named actions in every reachable phase;
- collision direction and draw order match the intended rule;
- score and game-over behavior match the chosen ownership mode;
- audio produces sound after user activation when audio changed;
- pointer/touch input works when the game claims mobile support.
For this repository's automated harness, also apply the tester contract in project-setup-and-modes.md. Do not impose that contract on unrelated user projects.
1---2name: developing-with-crisp-game-lib-23description: Creates or repairs browser mini-games specifically using crisp-game-lib. Use only when the user explicitly asks for crisp-game-lib or the existing project already uses it; skip for Godot, Unity, Phaser, canvas-only, or unspecified engine requests.4---56# Developing with crisp-game-lib78## Workflow9101. Inspect the existing project before choosing a setup. Preserve its pinned library version, entry style, helpers, and test harness.112. For a new project, choose CDN/classic-script or npm/bundler setup. Read [project-setup-and-modes.md](references/project-setup-and-modes.md) before creating entry files or selecting a version.123. State each named action and its physical bindings before coding. For a one-button game, state whether press, hold, or release acts and which phases are intentionally unused.134. Implement one clear frame order: input → state/physics → spawning → drawing/collision → scoring → game over.145. Apply the runtime contracts below and validate only behavior the change can reach. A new game or entry-point/input/audio/loop change needs a real-browser runtime check; a localized fix needs the affected check plus startup smoke.156. After the first working loop, record any interesting emergent behavior before deciding whether a collision artifact, draw-order effect, or physics interaction is a bug or a better mechanic.1617Use `if (!ticks) { ... }` for first-frame initialization in classic-script projects. In a bundler project, follow the existing `init({ update, title, description, characters, options })` entry style.1819## Runtime contracts2021- **Use documented APIs only.** Test mocks may expose globals absent from the browser bundle. Consult [api.md](references/api.md) for exact signatures, colors, sounds, collision properties, and options; use standard JavaScript or define any missing helper yourself.22- **Drawing order is collision order.** A shape detects only shapes drawn earlier in the same frame. Draw targets first and detectors second.23- **Treat `input.isJustPressed` as unified input.** It merges keyboard keys and pointer input. Use `keyboard.code[...]` for a named keyboard action and `pointer.isJustPressed` for pointer-only input. Unified input is appropriate for “any input starts.”24- **Define bindings once per named action.** Every phase must read the same synonym set. Multiple physical keys bound to one named action do not create additional game actions.25- **Keep library-owned and game-owned arcade cycles separate.** The normal cycle uses `title`, `description`, library score rendering, and `end()`. A custom attract/ceremony/name-entry cycle owns all of those. Read [project-setup-and-modes.md](references/project-setup-and-modes.md) before implementing or changing a custom cycle.26- **Verify audio audibly.** For built-in audio on crisp-game-lib 1.5.0+, load both algo-chip globals before the bundle and verify `algoChipSession != null` after first input. Missing globals silently disable `play()` and BGM.27- **Use current particle syntax.** Call `particle(pos, { count, speed, angle, angleWidth })`; do not introduce the legacy positional form.28- **Avoid `white` for visible art.** It matches the background across bundled themes. Use another color or a `light_*` variant.2930Minimal collision pattern:3132```javascript33color("red");34enemies.forEach((enemy) => box(enemy.pos, 10));3536color("blue");37if (box(player.pos, 8).isColliding.rect.red) {38 end();39}40```4142## Conditional references4344- Read [api.md](references/api.md) whenever exact library behavior matters. Its API enumeration is canonical; do not reconstruct it from memory.45- Read [examples.md](references/examples.md) only when a complete loop matching the requested control or game pattern would reduce implementation risk.46- Read [project-setup-and-modes.md](references/project-setup-and-modes.md) for CDN/npm skeletons, version pinning, default input bindings, custom arcade ownership, or this repository's simulator/tester constraints.4748## Validation4950Check the applicable items in a real browser:5152- startup has no console error or uncaught exception;53- controls map only to their named actions in every reachable phase;54- collision direction and draw order match the intended rule;55- score and game-over behavior match the chosen ownership mode;56- audio produces sound after user activation when audio changed;57- pointer/touch input works when the game claims mobile support.5859For this repository's automated harness, also apply the tester contract in [project-setup-and-modes.md](references/project-setup-and-modes.md). Do not impose that contract on unrelated user projects.