This file provides guidance to AI coding assistants when working with code in this repository.
crisp-game-lib is a JavaScript library for creating browser-based mini-games quickly and easily. It provides a simple API for drawing, collision detection, input handling, and sound effects. The library is designed for rapid prototyping of classic arcade-style games.
npm run watch_lib- Build the library with Rollup in watch modenpm run watch_games- Start development server for games on localhost:4000npm run generate_reference- Generate API documentation with TypeDocnpm run test- Run automated tests (Vitest)npm run test:watch- Run tests in watch mode
- Copy
docs/_templatedirectory todocs/[game-name] - Edit
docs/[game-name]/main.jsto implement your game - Run
npm run watch_gamesand openhttp://localhost:4000?[game-name]
main.ts- Main entry point, exports all public APIs, game loop coordinationloop.ts- Main game loop, rendering engine integration, theme managementview.ts- Canvas rendering, color management, drawing primitivesinput.ts- Mouse/touch/keyboard input handling with unified APIcollision.ts- Collision detection system based on drawing historyaudio.ts- Audio context management for sound effects and musicrandom.ts- Deterministic random number generationparticle.ts- Particle system for visual effectsletter.ts- Text rendering and character definitionsvector.ts- 2D vector math utilities
- Rollup bundles TypeScript source into
docs/bundle.jsas IIFE tsconfig.jsonfor main compilation,tsconfig-rollup.jsonfor bundling- Output includes TypeScript definitions at
docs/bundle.d.ts - When adding or modifying exported functions/variables in
src/main.ts, you must also update the corresponding type definitions indocs/bundle.d.tsto maintain TypeScript compatibility
Games are structured as:
title(string) - Game titledescription(string) - Game descriptioncharacters(array) - Pixel art character definitionsoptions(object) - Game configuration (screen size, theme, etc.)update()(function) - Main game loop called 60 times per secondaudioFiles(object) - Optional external audio file mappings
- Global game state via exported variables (
ticks,difficulty,score) - Functional API with drawing commands that return collision results
- Collision detection integrated into drawing operations
- Deterministic randomness for replay functionality
- Input abstraction supporting mouse, touch, and keyboard
- API reference generated at
docs/ref_document/ - Sample games in individual
docs/subdirectories - Each game has
main.jsandjsconfig.jsonfor IDE support
The project uses automated tests to complement manual visual testing:
- Test Framework: Vitest with happy-dom, @sinonjs/fake-timers, and pixelmatch
- Coverage: 70 tests covering core infrastructure (~1.3s execution time)
- Test Focus:
- Loop control (
src/loop.ts) - frame timing logic, initialization order - Input handling (
src/input.ts,src/button.ts) - pointer/keyboard state, button behavior - Replay system (
src/replay.ts) - state recording and restoration - Collision detection (
src/collision.ts) - hitbox generation, color shorthand propagation - Score system (
src/main.ts:addScore) - score updates, replay guard behavior, text centering
- Loop control (
- Purpose: Detect regressions in shared infrastructure when updating browsers, dependencies, or themes
To enable testing of critical internal code paths, test-only helper functions are available in src/main.ts:
__testSetReplaying(value: boolean)- Sets theisReplayingstate for testing replay guard behavior__testInitOptions(options: Options)- InitializescurrentOptionsfor testing option-dependent behavior
These functions are:
- Guarded by
process.env.NODE_ENV === "test"and have no impact on production code - Named with
__testprefix to clearly indicate test-only usage - Exported in both
src/main.tsanddocs/bundle.d.ts
Usage Example:
import {
__testSetReplaying,
__testInitOptions,
addScore,
score,
} from "../src/main";
// Test replay guard behavior
__testSetReplaying(true);
const scoreBefore = score;
addScore(100);
expect(score).toBe(scoreBefore); // Score unchanged during replay
// Test option-dependent behavior
__testInitOptions({ isUsingSmallText: false });
addScore(50, 100, 100); // Triggers centering logic with normal text sizeCollision detection is based on drawing history - shapes drawn with color("transparent") still participate in collision detection even though invisible.
- Use
simpleordarkthemes for better mobile performance - Avoid excessive
bar(),line(),arc()calls as they impact collision detection - WebGL themes (
pixel,shape,shapeDark,crt) may reduce performance on mobile
- Sound seeds generated from
title+descriptionstrings - External audio files supported via
audioFilesobject - Background music can be generated or loaded from files
Recommended control schemes for mobile:
- One-button games
- Left/right slide controls only
- Tap-specific locations on screen