aboutsummaryrefslogtreecommitdiff
path: root/CLAUDE.md
diff options
context:
space:
mode:
authorGene Pasquet <dev@etenil.net>2026-04-05 19:47:05 +0100
committerGene Pasquet <dev@etenil.net>2026-04-05 19:47:05 +0100
commit027053b11a3a5d861ed2fa2db245388bd95ac246 (patch)
tree84dfd90642bb6d8eb4e0e3fa3a9d651ba29b41e8 /CLAUDE.md
parent927f37639a3d5a0d881a5c8709f2cf577aadb15e (diff)
Progress
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md193
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.