diff options
| author | Gene Pasquet <dev@etenil.net> | 2026-04-07 23:36:12 +0100 |
|---|---|---|
| committer | Gene Pasquet <dev@etenil.net> | 2026-04-07 23:36:12 +0100 |
| commit | 19a5db8606a82830a5ccd0ed46d8e0cf3c95db0a (patch) | |
| tree | 241e7376014068ab9fc7a1bc8fa7a29cc1b62490 /docs/superpowers/plans/2026-04-05-milestone-14-docs.md | |
| parent | 618ed5fd6f5ae9c9f275c1e3cfb74762d7d51a01 (diff) | |
Work on demos
Diffstat (limited to 'docs/superpowers/plans/2026-04-05-milestone-14-docs.md')
| -rw-r--r-- | docs/superpowers/plans/2026-04-05-milestone-14-docs.md | 167 |
1 files changed, 0 insertions, 167 deletions
diff --git a/docs/superpowers/plans/2026-04-05-milestone-14-docs.md b/docs/superpowers/plans/2026-04-05-milestone-14-docs.md deleted file mode 100644 index 0688bf5..0000000 --- a/docs/superpowers/plans/2026-04-05-milestone-14-docs.md +++ /dev/null @@ -1,167 +0,0 @@ -# Milestone 14: End-User Documentation Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Write the 4 missing end-user documentation files (`docs/guide.org`, `docs/api.org`, `docs/entities.org`, `docs/physics.org`) that ship with the downstroke egg. - -**Architecture:** Each file is a self-contained org-mode document covering one aspect of the engine. Content is derived exclusively from the public API inventory provided in the task description and from the 5 existing demo games in `demo/`. No API fabrication -- only document what exists. Code examples should be drawn from or closely mirror the real demos. - -**Tech Stack:** Org-mode markup, Chicken Scheme code examples - ---- - -### Task 1: docs/guide.org -- Getting Started Guide - -**Files:** -- Create: `docs/guide.org` - -- [ ] **Step 1:** Write the file with these sections: - 1. **Title / Introduction** -- What downstroke is (2D tile-driven game engine for Chicken Scheme, built on SDL2) - 2. **Installation** -- `chicken-install downstroke`, system deps (SDL2, SDL2_mixer, SDL2_ttf, SDL2_image), egg deps - 3. **Hello World** -- Minimal ~20-line game: blank window that quits on Escape. Use `make-game` with just `title:`, `width:`, `height:` and an empty `update:` that does nothing. Call `game-run!`. Show the full import list needed. - 4. **Moving Square** -- Step up: add an entity with `#:x`, `#:y`, `#:width`, `#:height`; read input with `input-held?`; update position with `entity-set` + `apply-velocity-x`; use a custom `render:` hook to draw an SDL2 colored rect (mirror the shmup demo pattern: `sdl2:render-fill-rect!`). No tilemap needed -- set `tilemap: #f` and `tileset-texture: #f`. - 5. **Adding a Tilemap** -- Show how to load a TMX map in `preload:`, create a scene with it in `create:`, and let `render-scene!` handle drawing. Reference `demo/platformer.scm`. - 6. **Demo Overview** -- Table of the 5 demos with 1-line descriptions and what each demonstrates: - - `demo/platformer.scm` -- Gravity, jump, tile collision, camera follow, sound - - `demo/topdown.scm` -- 8-dir movement, no gravity, tilemap, camera follow - - `demo/sandbox.scm` -- Entity-entity collision, multi-entity physics, auto-respawn - - `demo/shmup.scm` -- No tilemap, entity spawning/removal, manual AABB collision, SDL colored rects - - `demo/audio.scm` -- Sound effects, music toggle, draw-ui-text - 7. **Build & Run** -- `make && make demos` to build everything; run a demo with `./bin/demo-platformer` (or however the Makefile names them) - 8. **Next Steps** -- Pointers to the other 3 doc files - -- [ ] **Step 2:** Self-review: verify every function/keyword used in code examples exists in the public API inventory. Verify import lists match what the real demos use. No fabricated API. - -**Key content notes:** -- The Hello World must actually work -- the minimum viable `make-game` call needs at least the `title:` keyword; all others have defaults (width 640, height 480, frame-delay 16, input-config uses `*default-input-config*`) -- `game-run!` handles SDL2 init, window creation, event loop, and cleanup -- the user does NOT call any SDL2 init themselves (except `init-audio!` for sound) -- Quit is automatic: the engine checks `(input-held? input 'quit)` every frame (bound to Escape + window close) - ---- - -### Task 2: docs/api.org -- Public API Reference - -**Files:** -- Create: `docs/api.org` - -- [ ] **Step 1:** Write the file with one top-level section per module, in this order: - 1. **Engine** (`downstroke/engine`) -- `make-game`, `game-run!`, `game-camera`, `game-asset`, `game-asset-set!`, `make-game-state`, `game-add-state!`, `game-start-state!`, `game-scene-set!`, auto-generated accessors (`game-renderer`, `game-input`, `game-window`, `game-title`, `game-width`, `game-height`, `game-scene`) - 2. **World** (`downstroke/world`) -- `make-scene`, `scene-entities`, `scene-entities-set!`, `scene-tilemap`, `scene-tileset-texture`, `scene-camera`, `scene-add-entity`, `scene-update-entities`, `scene-filter-entities`, `scene-find-tagged`, `scene-find-all-tagged`, `make-camera`, `camera-x`, `camera-y`, `camera-x-set!`, `camera-y-set!`, `camera-follow!` - 3. **Entity** (`downstroke/entity`) -- `entity-ref`, `entity-type`, `entity-set`, `entity-update` - 4. **Physics** (`downstroke/physics`) -- `apply-gravity`, `apply-acceleration`, `apply-velocity-x`, `apply-velocity-y`, `apply-jump`, `resolve-tile-collisions-x`, `resolve-tile-collisions-y`, `detect-ground`, `aabb-overlap?`, `resolve-entity-collisions`, `scene-resolve-collisions` - 5. **Input** (`downstroke/input`) -- `create-input-state`, `input-state-update`, `input-held?`, `input-pressed?`, `input-released?`, `input-any-pressed?`, `*default-input-config*`; include the default action/binding table - 6. **Renderer** (`downstroke/renderer`) -- `render-scene!`, `draw-ui-text`, `entity-screen-coords`, `entity-flip` - 7. **Assets** (`downstroke/assets`) -- `make-asset-registry`, `asset-set!`, `asset-ref` - 8. **Sound** (`downstroke/sound`) -- `init-audio!`, `load-sounds!`, `play-sound`, `load-music!`, `play-music!`, `stop-music!` - 9. **Animation** (`downstroke/animation`) -- `set-animation`, `animate-entity`; document the `#:animations` plist format - 10. **Tilemap** (`downstroke/tilemap`) -- `load-tilemap`, `tilemap-tileset`, `tileset-image`; note that TMX/TSX parsing uses expat - -- [ ] **Step 2:** For each function entry, include: - - Signature line in a `#+begin_src scheme` block - - 1-2 sentence description - - Brief code example where the usage is non-obvious (e.g., `scene-update-entities` taking variadic procs, `entity-set` returning a new plist, `make-game-state` + `game-add-state!` + `game-start-state!` flow) - -- [ ] **Step 3:** Self-review: cross-check every entry against the API inventory. Ensure no function is missing and no function is fabricated. Verify signatures match (especially keyword args for `make-game`, `make-scene`, `make-camera`, `make-game-state`). - -**Key content notes:** -- `make-game` keyword args: `title:` (default "Downstroke Game"), `width:` (640), `height:` (480), `frame-delay:` (16), `input-config:` (default `*default-input-config*`), `preload:`, `create:`, `update:`, `render:` (all default `#f`) -- `scene-update-entities` takes a scene + rest-arg list of procs, applies them sequentially to all entities -- `entity-set` is functional (returns new plist) -- this is critical to document clearly -- `game-scene` is auto-generated by defstruct, not manually defined -- `render-scene!` is called automatically by `game-run!` before the user's `render:` hook -- the user's `render:` is for overlays/UI - ---- - -### Task 3: docs/entities.org -- Entity Model & Prefabs - -**Files:** -- Create: `docs/entities.org` - -- [ ] **Step 1:** Write the file with these sections: - 1. **Entity Model Overview** -- Entities are plists (property lists), not objects or records. Pure data. No classes, no inheritance. Access via `entity-ref`, mutation via `entity-set` (which returns a new plist -- functional/immutable style). - 2. **Creating Entities** -- Show a literal plist creation: `(list #:type 'player #:x 100 #:y 200 ...)`. Explain that you just use `list` -- there is no `make-entity` constructor. - 3. **Plist Key Reference** -- Full table of all documented keys with type and description. Use the table from the API inventory verbatim: - - | Key | Type | Description | - |-----|------|-------------| - | `#:type` | symbol | Entity type | - | `#:x` `#:y` | number | World position | - | `#:width` `#:height` | number | Bounding box size | - | `#:vx` `#:vy` | number | Velocity | - | `#:ay` | number | Y acceleration (consumed by apply-acceleration) | - | `#:gravity?` | bool | Whether gravity applies | - | `#:on-ground?` | bool | Set by detect-ground | - | `#:solid?` | bool | Participates in entity-entity collision | - | `#:tile-id` | integer | Sprite index in tileset (1-indexed) | - | `#:facing` | number | 1 = right, -1 = left (affects flip) | - | `#:tags` | list of symbols | Used for scene-find-tagged | - | `#:animations` | alist | Animation data | - | `#:anim-name` | symbol | Current animation name | - | `#:anim-frame` | integer | Current frame index | - | `#:anim-tick` | integer | Tick counter for frame advance | - - 4. **Accessing & Updating Entities** -- `entity-ref` with default value, `entity-type` shortcut, `entity-set` (stress: returns NEW plist, original unchanged), `entity-update` with a proc. Show the let*-chaining pattern from the platformer demo. - 5. **Entities in Scenes** -- `scene-entities`, `scene-entities-set!`, `scene-add-entity`, `scene-update-entities` (show the sandbox demo pattern of passing multiple procs), `scene-filter-entities`, `scene-find-tagged` / `scene-find-all-tagged`. - 6. **Animation** -- The `#:animations` key format: `((idle #:frames (28) #:duration 10) (walk #:frames (27 28) #:duration 10))`. `set-animation` to switch, `animate-entity` to advance each frame. `#:tile-id` is updated automatically. - 7. **Tags** -- The `#:tags` key is a list of symbols. Use `scene-find-tagged` to find the first entity with a given tag, `scene-find-all-tagged` for all matches. Common pattern: tag the player with `'player`, enemies with `'enemy`. - -- [ ] **Step 2:** Self-review: verify all function signatures and plist keys match the API inventory exactly. - -**Key content notes:** -- Do NOT document prefab/mixin internals (`make-prefab-registry`, `instantiate-prefab` from scene-loader) beyond a brief mention -- these are in `scene-loader.scm` which is not in the public API inventory provided. Mention the concept exists and point to CLAUDE.md's description, but do not fabricate API signatures. -- The `#:animations` format uses keyword-style keys inside the alist entries -- this is unusual and worth a clear example. - ---- - -### Task 4: docs/physics.org -- Physics Pipeline & Collision - -**Files:** -- Create: `docs/physics.org` - -- [ ] **Step 1:** Write the file with these sections: - 1. **Overview** -- Downstroke provides a built-in physics pipeline for platformers and top-down games. All physics operates on entity plists -- functions take an entity and return a new entity. The pipeline is explicit: the user calls each step in their `update:` hook. - 2. **Pipeline Diagram** -- Show the 9-step pipeline order as a clear diagram: - ``` - apply-jump -> apply-acceleration -> apply-gravity -> - apply-velocity-x -> resolve-tile-collisions-x -> - apply-velocity-y -> resolve-tile-collisions-y -> - detect-ground -> resolve-entity-collisions - ``` - 3. **Pipeline Steps** -- One subsection per function. For each: signature, what entity keys it reads, what entity keys it writes/returns, and a 1-2 sentence explanation: - - `apply-jump` -- reads `#:on-ground?`, sets `#:ay` if pressed? and on-ground - - `apply-acceleration` -- reads `#:ay`, adds to `#:vy`, zeroes `#:ay` - - `apply-gravity` -- reads `#:gravity?`, adds gravity constant to `#:vy` - - `apply-velocity-x` -- reads `#:vx`, adds to `#:x` - - `resolve-tile-collisions-x` -- reads `#:x`, `#:width`, `#:vx`; snaps `#:x` on tile hit, zeroes `#:vx` - - `apply-velocity-y` -- reads `#:vy`, adds to `#:y` - - `resolve-tile-collisions-y` -- reads `#:y`, `#:height`, `#:vy`; snaps `#:y` on tile hit, zeroes `#:vy` - - `detect-ground` -- probes 1px below entity feet, sets `#:on-ground?` - - `resolve-entity-collisions` / `scene-resolve-collisions` -- all-pairs push-apart for entities with `#:solid? #t` - 4. **Tile Collision Model** -- AABB overlap detection. The physics module checks all tile cells overlapping the entity's bounding box. On collision, the entity is snapped to the nearest tile edge in the direction of travel. X and Y axes are resolved independently (hence the interleaved velocity/collision pattern). - 5. **Entity-Entity Collision** -- `aabb-overlap?` for manual checks; `resolve-entity-collisions` for automatic push-apart. Entities must have `#:solid? #t` to participate. `scene-resolve-collisions` is the convenience wrapper. - 6. **Platformer Example** -- Full `update:` lambda from `demo/platformer.scm` (verbatim or near-verbatim). Annotate the let*-chain showing each pipeline step. - 7. **Top-Down Example** -- Full `update:` lambda from `demo/topdown.scm`. Highlight that `apply-gravity`, `apply-jump`, `apply-acceleration`, and `detect-ground` are skipped; only velocity + tile-collision steps are used. Set `#:gravity? #f` on entities. - 8. **Physics Sandbox Example** -- Show the `scene-update-entities` pattern from `demo/sandbox.scm` where multiple physics procs are passed as rest args. Show `scene-resolve-collisions` for entity-entity push-apart. - -- [ ] **Step 2:** Self-review: verify all function names, signatures, and entity key names match the API inventory. Ensure the pipeline order matches exactly. Verify code examples are accurate against the real demo source files. - -**Key content notes:** -- The pipeline is NOT automatic -- the user must call each step explicitly in their `update:` hook. This is by design (flexibility for top-down vs platformer vs custom). -- `resolve-tile-collisions-x` and `resolve-tile-collisions-y` take `(entity tilemap)` -- the tilemap must be passed in. -- `detect-ground` also takes `(entity tilemap)`. -- `apply-jump` takes `(entity pressed?)` where pressed? is typically `(input-pressed? input 'a)`. -- `scene-update-entities` with rest-arg procs is the idiomatic way to apply physics to all entities at once (sandbox pattern). - ---- - -## Rejected Alternatives - -- **Single monolithic doc file**: Rejected. Four focused files are easier to navigate and maintain. Each serves a different reader need (tutorial vs reference vs concept guide). -- **Auto-generated API docs from source**: Rejected. Chicken Scheme has no standard doc-generation tool that would produce org-mode output. Hand-written docs allow better examples and narrative. -- **Markdown instead of org-mode**: Rejected. CLAUDE.md explicitly requires org-mode format. - -## Gaps -- follow-up investigation needed - -- **Tilemap public API**: The API inventory lists `load-tilemap`, `tilemap-tileset`, and `tileset-image` but the full set of tilemap accessors (e.g., `tilemap-layers`, tile GID access) was not provided. `docs/api.org` should document only the three confirmed exports; if more exist, they can be added later. -- **Prefab/scene-loader API**: `scene-loader.scm` exports `instantiate-prefab` and likely `make-prefab-registry`, but these were not in the provided API inventory. `docs/entities.org` should mention the concept but not fabricate signatures. A follow-up investigation of `scene-loader.scm` would allow documenting these fully. -- **Animation internals**: The exact behavior of `animate-entity` (how it advances `#:anim-tick`, when it wraps `#:anim-frame`, how it sets `#:tile-id`) was not fully specified. Document the public interface only. |
