aboutsummaryrefslogtreecommitdiff
path: root/docs/superpowers/specs/2026-04-05-demos-design.md
diff options
context:
space:
mode:
authorGene Pasquet <dev@etenil.net>2026-04-07 23:36:12 +0100
committerGene Pasquet <dev@etenil.net>2026-04-07 23:36:12 +0100
commit19a5db8606a82830a5ccd0ed46d8e0cf3c95db0a (patch)
tree241e7376014068ab9fc7a1bc8fa7a29cc1b62490 /docs/superpowers/specs/2026-04-05-demos-design.md
parent618ed5fd6f5ae9c9f275c1e3cfb74762d7d51a01 (diff)
Work on demos
Diffstat (limited to 'docs/superpowers/specs/2026-04-05-demos-design.md')
-rw-r--r--docs/superpowers/specs/2026-04-05-demos-design.md256
1 files changed, 0 insertions, 256 deletions
diff --git a/docs/superpowers/specs/2026-04-05-demos-design.md b/docs/superpowers/specs/2026-04-05-demos-design.md
deleted file mode 100644
index 78ed3f4..0000000
--- a/docs/superpowers/specs/2026-04-05-demos-design.md
+++ /dev/null
@@ -1,256 +0,0 @@
-# Downstroke Demo Games Design
-
-**Date:** 2026-04-05
-**Status:** Approved
-**Scope:** `demo/` folder, 5 demo games, Makefile `make demos` target, CLAUDE.md update
-
----
-
-## Goal
-
-Provide 5 small self-contained demo games in `demo/` that collectively exercise every engine system. Each demo compiles to its own executable (`bin/demo-*`). They replace the macroknight integration test for Milestone 8 and serve as living documentation of the engine API.
-
----
-
-## File Layout
-
-```
-demo/
- assets/ ← copied from macroknight/assets (not symlinked)
- monochrome-transparent.png ← tileset spritesheet
- monochrome_transparent.tsx ← tileset metadata (TSX)
- level-0.tmx ← level used by platformer, topdown, sandbox
- DejaVuSans.ttf ← font for audio demo text
- jump.wav ← sound effect (platformer jump, shmup shoot)
- theme.ogg ← music (audio demo)
- platformer.scm
- shmup.scm
- topdown.scm
- audio.scm
- sandbox.scm
-```
-
-**Omitted from copy:** `prefabs.scm`, `macroknight.tiled-project`, `macroknight.tiled-session` — macroknight-specific files not needed by any demo.
-
-**Audio modules:** `mixer.scm` and `sound.scm` are copied from `macroknight/` into the downstroke repo root and added to the build. They are engine-level modules and are required by any demo that uses audio.
-
-When copying `sound.scm`, add one function that macroknight's version omits:
-```scheme
-(define (stop-music!) (mix-halt-music))
-```
-The audio demo uses `stop-music!` to toggle music off.
-
----
-
-## Build
-
-### Makefile additions
-
-```makefile
-DEMO_NAMES := platformer shmup topdown audio sandbox
-DEMO_BINS := $(patsubst %,bin/demo-%,$(DEMO_NAMES))
-
-demos: engine $(DEMO_BINS)
-
-bin/demo-%: demo/%.scm $(OBJECT_FILES) | bin
- csc demo/$*.scm $(OBJECT_FILES) -o bin/demo-$* -I bin
-```
-
-- `make` — builds engine modules only (unchanged)
-- `make demos` — builds all 5 demo executables; depends on engine being built first
-- Demos are compiled as programs (not units), linked against all engine `.o` files
-- `$(OBJECT_FILES)` includes `mixer` and `sound` once those modules are added to `MODULE_NAMES`
-
-### `render-scene!` nil guards
-
-`render-scene!` in `renderer.scm` is updated so that entity drawing is **nested inside** the tilemap guard:
-
-- Tilemap drawing only fires if `(scene-tilemap scene)` is not `#f`
-- Entity drawing only fires if **both** `(scene-tilemap scene)` AND `(scene-tileset-texture scene)` are not `#f`
-
-```scheme
-(when tilemap
- (draw-tilemap renderer camera tileset-texture tilemap)
- (when tileset-texture
- (let ((tileset (tilemap-tileset tilemap)))
- (draw-entities renderer camera tileset tileset-texture entities))))
-```
-
-**Consequence for shmup:** since shmup has no tilemap, the engine will not draw its entities. Shmup draws its player, bullets, and enemies as **colored SDL rectangles** in its `render:` hook — matching the original "colored rects" intent. This is acceptable because shmup entities are simple geometric shapes, not sprites.
-
-Audio (no scene at all) works because `engine.scm` guards `render-scene!` with `(when (game-scene game) ...)`.
-
-### CLAUDE.md update
-
-Add to the Build & Test section:
-
-> `make demos` must always succeed. A demo that fails to compile is a build failure. Run `make && make demos` to verify both engine and demos build cleanly.
-
----
-
-## Demo Code Pattern
-
-Every demo follows this ~30-line structure:
-
-```scheme
-(import (prefix sdl2 "sdl2:")
- (prefix sdl2-ttf "ttf:")
- (prefix sdl2-image "img:")
- downstroke/engine
- downstroke/world
- downstroke/tilemap
- downstroke/renderer
- downstroke/input
- downstroke/physics
- downstroke/assets)
-
-(define *game*
- (make-game
- title: "Demo: <Name>" width: 600 height: 400
- preload: (lambda (game) ...) ;; load tilemap, tileset texture, sounds
- create: (lambda (game) ...) ;; build scene, place entities
- update: (lambda (game dt) ...) ;; input dispatch, physics calls
- render: (lambda (game) ...))) ;; HUD overlay (optional)
-
-(game-run! *game*)
-```
-
-Tile IDs in entity plists are placeholder values — to be adjusted visually after first run.
-
----
-
-## The 5 Demos
-
-### 1. `demo/platformer.scm` — Platformer
-
-**Systems exercised:** `input`, `physics` (gravity + tile collision), `renderer` (tilemap + entities), `world`/scene, camera follow, audio (sound effect)
-
-**Mechanics:**
-- Player entity with gravity, left/right movement, jump
-- Tile collision via `apply-physics` from `physics.scm`
-- Camera follows player horizontally
-- Jump sound via `(play-sound 'jump)` (loaded in preload: as `'(jump . "demo/assets/jump.wav")`)
-- Level: `demo/assets/level-0.tmx`
-- Tile IDs: placeholder (user adjusts)
-
-**Key entity plist:**
-```scheme
-(list #:type 'player
- #:x 100 #:y 50
- #:width 16 #:height 16
- #:vx 0 #:vy 0
- #:gravity? #t
- #:on-ground? #f
- #:tile-id 1)
-```
-
-**Update logic:** read input → set `#:vx` from left/right → jump sets `#:vy` → call physics step → update camera x to follow player x.
-
----
-
-### 2. `demo/shmup.scm` — Shoot-em-up
-
-**Systems exercised:** `entity` (spawning/removal), manual AABB entity-entity collision (removal-based, not `physics.scm`), `input`, `renderer` (SDL colored rects), `world`/scene (no tilemap)
-
-**Mechanics:**
-- Player ship at bottom, moves left/right
-- Space bar fires bullet upward (new entity added to scene)
-- Enemies spawn from top at random x positions every N frames, move downward
-- Bullet-enemy collision: both entities removed from scene
-- No tilemap — plain background (black/SDL clear)
-- No gravity on any entity
-- `jump.wav` plays on shoot
-
-**Key entity plists:** (no `#:tile-id` — entities are drawn as colored rects)
-```scheme
-;; player
-(list #:type 'player #:x 280 #:y 360 #:width 16 #:height 16 #:vx 0 #:vy 0)
-;; bullet
-(list #:type 'bullet #:x px #:y 340 #:width 4 #:height 8 #:vx 0 #:vy -5)
-;; enemy
-(list #:type 'enemy #:x rx #:y 0 #:width 16 #:height 16 #:vx 0 #:vy 2)
-```
-
-**Rendering:** shmup has no tilemap, so `render-scene!` draws nothing for this scene. Shmup implements its own `render:` hook using `sdl2:render-fill-rect!` with distinct colors (player = white, bullet = yellow, enemy = red). The camera is at (0,0) so screen coords == world coords.
-
-**Update logic:** move entities by vx/vy each frame → manual AABB collision check between bullets and enemies (not `resolve-entity-collisions` — shmup uses removal, not push-apart) → filter removed entities from scene → spawn new enemy every 60 frames → read input for player movement and shoot.
-
----
-
-### 3. `demo/topdown.scm` — Top-down explorer
-
-**Systems exercised:** `input` (8-directional), `renderer` (tilemap + entity), `world`/scene, camera follow (both axes), `physics` (no gravity)
-
-**Mechanics:**
-- Player entity moves in 8 directions (WASD or arrows)
-- No gravity (`#:gravity? #f`)
-- Camera follows player on both x and y axes
-- Level: `demo/assets/level-0.tmx` (same tilemap, different movement feel)
-- Tileset texture loaded in preload: — required for entity sprite rendering (tilemap + tileset-texture both present so render-scene! draws entities via tileset)
-- No audio
-
-**Update logic:** read input → set `#:vx` and `#:vy` from direction keys → apply tile collision (no gravity component) → update camera to center on player.
-
----
-
-### 4. `demo/audio.scm` — Audio showcase
-
-**Systems exercised:** audio (sound effects + music), `renderer` (text via `draw-ui-text`), `input`, `assets`
-
-**Mechanics:**
-- Static screen with text instructions rendered via `draw-ui-text`
-- Press **J** → play `jump.wav`
-- Press **M** → toggle `theme.ogg` music on/off
-- Press **Escape** → quit
-- No tilemap, no physics, no moving entities
-- Uses `DejaVuSans.ttf` for text
-- Audio calls via `sound.scm` functions: `load-sounds!`, `play-sound`, `load-music!`, `play-music!`, `stop-music!` (added when copying sound.scm — see File Layout)
-
-**Display:** colored rectangle background + text labels for each key binding.
-
----
-
-### 5. `demo/sandbox.scm` — Physics sandbox
-
-**Systems exercised:** `physics` (gravity + tile collision + entity-entity collision), `renderer`, `world`/scene, no player input
-
-**Mechanics:**
-- 10 entities spawned at random x positions near the top of the screen
-- All have `#:gravity? #t` and `#:solid? #t` (required for `resolve-entity-collisions` to participate)
-- Physics step runs each frame (gravity accelerates, tile collision stops them)
-- Entities rest on floor tiles or bounce (depending on physics.scm behavior)
-- No player — pure observation of physics pipeline
-- Level: `demo/assets/level-0.tmx`
-- After all entities settle (or after 10 seconds), loop: despawn all, respawn at new random positions
-
----
-
-## Systems Coverage Matrix
-
-| System / Module | platformer | shmup | topdown | audio | sandbox |
-|---|---|---|---|---|---|
-| `engine` (make-game, game-run!) | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `input` | ✓ | ✓ | ✓ | ✓ | — |
-| `physics` (gravity) | ✓ | — | — | — | ✓ |
-| `physics` (tile collision) | ✓ | — | ✓ | — | ✓ |
-| `physics` (entity collision) | — | — | — | — | ✓ |
-| manual AABB (removal) | — | ✓ | — | — | — |
-| `renderer` (tilemap) | ✓ | — | ✓ | — | ✓ |
-| `renderer` (entities) | ✓ | — | ✓ | — | ✓ |
-| `renderer` (SDL colored rects) | — | ✓ | — | — | — |
-| `renderer` (text) | — | — | — | ✓ | — |
-| `world` / scene | ✓ | ✓ | ✓ | — | ✓ |
-| `assets` registry | ✓ | ✓ | ✓ | ✓ | ✓ |
-| audio (sound) | ✓ | ✓ | — | ✓ | — |
-| audio (music) | — | — | — | ✓ | — |
-| camera follow | ✓ (x) | — | ✓ (xy) | — | — |
-
----
-
-## Out of Scope
-
-- Animation state machine (`animation.scm`) — not yet extracted to downstroke
-- AI (`ai.scm`) — not yet extracted
-- Prefab system — not yet extracted
-- Scene transitions — Milestone 9
-- Asset-type-specific load helpers (`game-load-tilemap!` etc.) — Milestone 6