diff options
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 193 |
1 files changed, 0 insertions, 193 deletions
diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index fb196e5..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,193 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## What this is - -**Downstroke** is a 2D tile-driven game engine for Chicken Scheme, built on SDL2. API inspired by Phaser 2: a minimal game is ~20 lines of Scheme. - -The engine is being extracted from the testbed game **macroknight** (`/home/gene/src/macroknight`). Milestones 1–6 are pure refactoring (no behavior changes); Milestone 7 is the design pivot where the public API stabilizes. - -**Detailed extraction plan**: `/home/gene/src/macroknight/TODO-engine.org` -**Project milestones**: `/home/gene/Documents/Perso/Projects/downstroke.org` (also in README.org) - -## Target API - -```scheme -(define my-game - (make-game - title: "My Game" width: 600 height: 400 - preload: (lambda (game) ...) ; load assets - create: (lambda (game) ...) ; init scene - update: (lambda (game dt) ...))) ; game-specific logic (physics runs first) - -(game-run! my-game) -``` - -Built-in physics pipeline (runs before user `update:` hook): -``` -input → acceleration → gravity → velocity-x → tile-collision-x → -velocity-y → tile-collision-y → ground-detection → entity-collisions -``` - -## Build & Test (macroknight — source of truth) - -All engine code currently lives in `/home/gene/src/macroknight`. Until Milestone 1 is complete, build and test from there. - -```bash -cd /home/gene/src/macroknight - -make # compile all modules + link bin/game -make test # run all 8 SRFI-64 test suites via csi -make clean # remove bin/ and .import.scm files - -# Run a single test module: -csi -s tests/physics-test.scm -csi -s tests/entity-test.scm -# etc. -``` - -Once extraction begins, the downstroke Makefile must also build all demos: - -```bash -make # compile engine + all demos in demo/ -make test # run all SRFI-64 test suites -make demos # build demo games only (verify they compile) -``` - -**Module compile order** (dependency order, must be respected in Makefile): -`tilemap → entity → world → animation → physics → ai → input → prefabs → mixer → sound` - -Modules are compiled as **units** (`csc -c -J -unit $*`) to avoid C toplevel name collisions when linking multiple `.o` files. Each module generates both a `.o` and a `.import.scm` in `bin/`. - -## Test-Driven Development - -**Tests are mandatory for all engine code.** Write tests before or alongside implementation — never after. The test suite is the primary correctness guarantee for the engine, since behavior regressions are easy to introduce during extraction. - -- Test files live in `tests/`, named `<module>-test.scm` -- Framework: SRFI-64 (`test-begin`, `test-equal`, `test-assert`, `test-end`) -- Tests run via `csi -s` (interpreter, not compiled) and must not require SDL2 — mock or stub any SDL2-dependent code -- Each engine module must have a corresponding test module before the module is considered done - -## Documentation - -End-user documentation lives in `docs/` as **org-mode files** and must be kept up to date as the API evolves. This is not optional — docs ship with the egg. - -- `docs/api.org` — public API reference (`make-game`, `game-run!`, all accessors and hooks) -- `docs/guide.org` — getting started guide with the minimal ~20-line game example -- `docs/entities.org` — entity model, plist keys, prefab/mixin system -- `docs/physics.org` — physics pipeline, collision model, gravity/velocity API - -When adding or changing any public-facing function or keyword argument, update the relevant doc file in the same commit. - -## Demo Games - -`demo/` contains small self-contained example games that exercise the engine API. They serve as living documentation and integration tests. - -- Each demo is a single `.scm` file (plus any assets in `demo/<name>/`) -- The Makefile must build all demos as part of `make` or `make demos` — a demo that fails to compile is a build failure -- Demos should be minimal: one mechanic per demo (gravity+jump, tilemap rendering, animation, etc.) -- Do not add game-specific logic to the engine to make a demo work; if a demo needs something, it belongs in the engine's public API - -## Engine Module Architecture - -| Module | File | Responsibility | -|---|---|---| -| `engine` | engine.scm | `make-game`, `game-run!`, lifecycle orchestration | -| `world` | world.scm | Scene struct, entity list ops, camera | -| `entity` | entity.scm | Entity plist accessors (`entity-ref`, `entity-set`, `entity-type`) | -| `physics` | physics.scm | Gravity, velocity, AABB tile + entity collisions, ground detection | -| `tilemap` | tilemap.scm | TMX/TSX XML parsing (expat), tileset loading, tile rect calculations | -| `input` | input.scm | SDL2 event → action mapping, keyboard/joystick/controller | -| `animation` | animation.scm | Frame/tick tracking, sprite ID mapping, animation state machine | -| `prefabs` | prefabs.scm | Mixin composition, prefab data loading, entity instantiation + hooks | -| `ai` | ai.scm | FSM-based enemy AI (idle/patrol/chase) via `states` egg | -| `renderer` | renderer.scm | SDL2 drawing abstraction: `draw-sprite`, `draw-tilemap-layer`, `draw-text` | -| `assets` | assets.scm | Asset registry for `preload:` lifecycle hook | -| `scene-loader` | scene-loader.scm | `game-load-scene!`, `instantiate-prefab` | -| `sound` | sound.scm | Sound registry, music playback | -| `mixer` | mixer.scm | SDL_mixer FFI bindings (no Scheme dependencies) | - -## Entity Model - -Entities are **plists** (property lists) — no classes, pure data + functions: - -```scheme -(list #:type 'player - #:x 100 #:y 200 - #:width 16 #:height 16 - #:vx 0 #:vy 0 - #:gravity? #t - #:on-ground? #f - #:tile-id 29 ; sprite index in tileset - #:tags '(player) - #:anim-name 'walk - #:animations ((idle #:frames (28) #:duration 10) - (walk #:frames (27 28) #:duration 10))) -``` - -Key shared entity keys: `#:type`, `#:x`, `#:y`, `#:width`, `#:height`, `#:vx`, `#:vy`, `#:tile-id`, `#:tags`. - -Access via `entity-ref`, `entity-set` (returns new plist — functional/immutable), `entity-type`. - -## Scene & Camera - -```scheme -(make-scene - entities: (list ...) - tilemap: tm - camera: (make-camera x: 0 y: 0) - tileset-texture: tex) -``` - -## Prefab / Mixin System - -```scheme -(mixins - (physics-body #:vx 0 #:vy 0 ...) - (has-facing #:facing 1)) - -(prefabs - (player physics-body has-facing #:type player #:tile-id 29 ...)) -``` - -Prefabs are loaded from a data file (`assets/prefabs.scm`). `instantiate-prefab` merges mixins + overrides into a fresh entity plist. - -## Tile Collision Model - -Tiles come from TMX maps (Tiled editor). The tilemap module parses TMX XML via expat into a struct with layers, tile GIDs, and a tileset. Collision tiles are identified by metadata in the TSX tileset. The physics module checks all tile cells overlapping an entity's AABB and snaps the entity to the nearest edge (velocity-direction-aware). - -## AI State Machine - -Uses the `states` egg. States: `idle → patrol → chase → patrol` (cycles back). Guards: `player-in-range?`, `player-in-attack-range?`, `chase-give-up?`. After Milestone 10, hardcoded `'player` type checks are replaced with `(scene-find-tagged scene 'player)`. - -## Dependencies - -System: `SDL2`, `SDL2_mixer`, `SDL2_ttf`, `SDL2_image` - -Chicken eggs: `sdl2`, `sdl2-image`, `expat`, `matchable`, `defstruct`, `states`, `srfi-64` (tests), `srfi-197` - -## Egg Packaging - -Downstroke is distributed as a **Chicken egg** named `downstroke`. The egg spec (`downstroke.egg`) declares all modules as installable units. Once published, games depend on it via `chicken-install downstroke`. - -Module namespacing follows the egg convention: `downstroke/physics`, `downstroke/world`, etc. All module source files live at the project root; the egg spec maps them to the namespaced identifiers. - -## Macroknight Port - -As soon as the first installable egg exists (Milestone 11), macroknight must be ported to depend on it. This is an ongoing obligation — macroknight is the primary validation that the engine API is usable. Any engine change that requires macroknight to be updated should update macroknight in the same work session. - -The ported macroknight `game.scm` is the definition of "Milestone 12 done": it should be ~20–30 lines, containing only `make-game` + lifecycle hooks + `game-run!`. - -## Tracking Progress - -As milestones and tasks are completed, update the TODO items in `/home/gene/Documents/Perso/Projects/downstroke.org`. Mark tasks with `DONE` as they are finished — this file is the authoritative project tracker. - -## Milestone Status - -Milestones 1–6: pure refactoring — extract modules into the project root, no behavior changes. -Milestone 7: design pivot — `make-game` + `game-run!` public API becomes stable. -Milestones 8–10: camera follow, scene state machine, AI tag lookup. -Milestones 11–12: package as Chicken egg, macroknight uses it as dependency. - -Current status: all milestones at 0/N — extraction has not yet begun. |
