|
1 | | -# MVP-2 Zelda-lite — asset spec |
2 | | - |
3 | | -Drop assets in this directory (`examples/rpg/`). Manifest format |
4 | | -matches `examples/shooter/manifest.txt`. Once delivered, the engine |
5 | | -+ level files get scaffolded as `rpg.bas`, `level1.bas`, |
6 | | -`level1_cave.bas`, all consuming `maplib.bas` (per |
7 | | -`docs/map-format.md`). |
8 | | - |
9 | | -## Required |
10 | | - |
11 | | -### Tilesets — exercises multi-tileset support |
12 | | - |
13 | | -``` |
14 | | -overworld.png 256x128 cellW=32 cellH=32 32 tiles: grass, water, sand, |
15 | | - path, tree, rock, fence, sign, |
16 | | - flowers, etc. |
17 | | -cave.png 256x128 cellW=32 cellH=32 32 tiles: stone floor, wall, |
18 | | - door, stairs, torch, chest, |
19 | | - cracked-wall variant. |
20 | | -``` |
21 | | - |
22 | | -### Player + NPCs + enemies |
23 | | - |
24 | | -``` |
25 | | -link.png 160x32 cellW=32 cellH=32 5 frames: idle + up + down + |
26 | | - left + right (one frame each; |
27 | | - animate later). |
28 | | -npc.png 32x32 single friendly NPC sprite |
29 | | - (old man / merchant). |
30 | | -enemy.png 64x32 cellW=32 cellH=32 1 enemy, 2-frame walk anim |
31 | | - (slime / octorok). |
32 | | -``` |
33 | | - |
34 | | -## Optional (skip if shipping faster matters) |
35 | | - |
36 | | -``` |
37 | | -items.png 64x16 cellW=16 cellH=16 4 items: heart, key, sword, |
38 | | - gem (chest drops + HUD). |
39 | | -heart.png 8x8 HUD heart pip (lives display). |
40 | | -effects.png 32x32 sword-slash / sparkle one-shot. |
41 | | -``` |
42 | | - |
43 | | -## Per-tileset metadata to provide |
44 | | - |
45 | | -For each tileset, list the **local tile ids** that fall into each |
46 | | -category. (Per the format spec, ids are 1-based local to each sheet; |
47 | | -0 = blank.) |
48 | | - |
49 | | -### `overworld.png` |
50 | | - |
51 | | -- **solid** (block player + projectiles): _list ids_ |
52 | | -- **damaging** + damage value (lava / spikes — optional): _list ids_ |
53 | | -- **kind: door** — id of any tile that triggers map transition on |
54 | | - walk-into: _list ids_ |
55 | | - |
56 | | -### `cave.png` |
57 | | - |
58 | | -- **solid**: _list ids_ |
59 | | -- **kind: door** (back to overworld): _list ids_ |
60 | | -- **kind: chest** (interactable, drops items): _list ids_ |
61 | | - |
62 | | -## Design choices to confirm before scaffold |
63 | | - |
64 | | -| Decision | Default proposal | |
| 1 | +# MVP-2 Zelda-lite — assets in this folder |
| 2 | + |
| 3 | +Using OpenGameArt **"Zelda-like Tilesets and Sprites"** by ArMM1998 |
| 4 | +(originally https://opengameart.org/content/zelda-like-tilesets-and-sprites). |
| 5 | +Tiles are **16×16**, character/NPC sprites are **16×32**. Verify |
| 6 | +license before public release (typically CC0 for this pack). |
| 7 | + |
| 8 | +Reference images with numbered cells exist alongside each sheet: |
| 9 | +`Overworld_ref.png`, `cave_ref.png`, `objects_ref.png`, |
| 10 | +`character_ref_16x32.png`, `NPC_test_ref.png`. Regenerate with |
| 11 | +`/tmp/tile_ref.py`. |
| 12 | + |
| 13 | +## Sheet inventory |
| 14 | + |
| 15 | +| File | Size | Cell | Grid | Tiles | |
| 16 | +|-------------------|----------|-------|---------|-------| |
| 17 | +| `Overworld.png` | 640×576 | 16×16 | 40×36 | 1440 | |
| 18 | +| `cave.png` | 640×400 | 16×16 | 40×25 | 1000 | |
| 19 | +| `Inner.png` | 640×400 | 16×16 | 40×25 | 1000 | |
| 20 | +| `objects.png` | 528×320 | 16×16 | 33×20 | 660 | |
| 21 | +| `log.png` | 192×128 | 16×16 | 12×8 | 96 | |
| 22 | +| `font.png` | 240×144 | — | — | — | |
| 23 | +| `character.png` | 272×256 | 16×32 | 17×8 | 136 | |
| 24 | +| `NPC_test.png` | 64×128 | 16×32 | 4×4 | 16 | |
| 25 | + |
| 26 | +## MVP-1 picks (subject to user revision) |
| 27 | + |
| 28 | +### Overworld tile ids |
| 29 | +- Walkable: grass `1` (also 4,5,6 = grass variants) |
| 30 | +- Path/dirt: `49` |
| 31 | +- Sand: `204` |
| 32 | +- **solid** (water + tree + rock + walls): water family `17–22, 57–62`, |
| 33 | + rock `15, 28`, building wall — TBD when authored |
| 34 | +- **door** (warp to cave): TBD pick (guess `67`) |
| 35 | + |
| 36 | +### Cave tile ids |
| 37 | +- Floor: `2` (darkgray) |
| 38 | +- **solid** (wall): `162, 163, 164, 168` family + water `282` |
| 39 | +- **stairs** (warp to overworld): TBD pick (guess `168`) |
| 40 | + |
| 41 | +### Sprite picks |
| 42 | +- **Player** (`character.png` 16×32): |
| 43 | + - down idle: frame 1 (used in MVP-1) |
| 44 | + - down walk: frames 1–4 |
| 45 | + - left/up/right/sword: TBD (rows 2, 3, 4, 5) |
| 46 | +- **NPC** (`NPC_test.png` 16×32): frame 1 (single bald guy) |
| 47 | +- **Enemy**: not in pack — placeholder = tint NPC red, or skip |
| 48 | + |
| 49 | +## Map design |
| 50 | + |
| 51 | +| Decision | Value | |
65 | 52 | |---|---| |
66 | | -| Overworld map size | 32 × 32 cells (1024 × 1024 px world) | |
67 | | -| Room size | 8 × 8 cells → 4 × 4 grid = 16 rooms (Zelda 1 screen-flip) | |
68 | | -| Cave map | separate file `level1_cave.bas`, 8 × 8 cells (single room) | |
69 | | -| Door pairing | one overworld door → cave entry; cave stairs → back to overworld | |
70 | | -| Combat | sword swipe on bump — kills enemy if facing it (no projectiles) | |
71 | | -| NPC interact | walk-into-NPC opens dialogue text in HUD strip; E or SPACE dismisses | |
72 | | -| Camera mode | `room` — snap to current 8×8 room on player crossing boundary | |
| 53 | +| Overworld map size | 32 × 32 cells (512 × 512 px world) | |
| 54 | +| Room size | 20 × 12 cells = 320 × 192 px (full viewport less HUD strip) | |
| 55 | +| Room grid | overworld is 1.6 × 2.6 rooms — adjusted to 1 large area for MVP-1 | |
| 56 | +| Cave map | `level1_cave.bas`, 20 × 12 cells (single room) | |
| 57 | +| Door pairing | one overworld door tile → cave entry; cave stair tile → back | |
| 58 | +| Combat | sword swipe on bump (deferred — MVP-1 is exploration only) | |
| 59 | +| NPC interact | walk-into-NPC opens dialogue text in HUD; SPACE dismisses | |
| 60 | +| Camera mode | `room` — snap to current room on player crossing boundary | |
73 | 61 | | HUD | top 24 px strip: hearts (lives) + dialogue text | |
74 | 62 |
|
75 | 63 | ## What this MVP validates in `docs/map-format.md` |
76 | 64 |
|
77 | | -- **multi-tileset map** (`tilesets[]` length 2; layers reference |
78 | | - `tilesetId`) |
79 | | -- **multi-layer rendering** (terrain + decoration + hidden collision) |
80 | | -- **camera.mode = "room"** snap behaviour |
81 | | -- **door pairing** via `props.leadsTo` + `props.spawnAt` |
82 | | -- **objects** with `kind: npc | enemy | door | chest | spawn` |
83 | | -- **per-instance state** vs static tile flag (player has key 5 lives |
84 | | - in savegame domain; tile.solid is static tileset metadata) |
| 65 | +- multi-tileset map (`tilesets[]` length 2; layers reference `tilesetId`) |
| 66 | +- multi-layer rendering (terrain + decoration + collision) |
| 67 | +- `camera.mode = "room"` snap behaviour |
| 68 | +- door pairing via `props.leadsTo` + `props.spawnAt` |
| 69 | +- objects with `kind: npc | door | spawn` |
85 | 70 |
|
86 | | -Together with MVP-1 shooter, every concept in v1 of the format |
87 | | -(except polygon shapes — explicitly deferred) gets exercised. |
| 71 | +Polygon collision shapes — explicitly deferred (per format spec). |
0 commit comments