Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/art-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ jobs:
- run: python scripts/creek_layers.py
- run: python scripts/split_layers.py --check
- run: python scripts/collision_check.py
- run: python scripts/export_stage.py --verify --out tmp/stage-export
- run: python scripts/check_docs.py
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ tmp/
*.log
.DS_Store
Thumbs.db

# Generated by scripts/export_stage.py from art/stages/ (never committed)
game/public/assets/stages/
9 changes: 9 additions & 0 deletions art/stages/hidden-garden/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Hidden Garden – stage chunks

The prologue, drawn from the approved [Hidden Garden concept](../../locations/hidden-garden-clean.md) as a flat side elevation with its figures removed. One chunk, `hg-0-0` (2160×720): the bench where Dexter sits at the start (x ≈ 190–320), the stone path and the timber jetty (path top y = 441), the end of the jetty where Dexter points (x ≈ 1290–1323), and one wrong patch in the pond's reflection below it – a rusty girder with a ladder that isn't there. Clean only.

**Layers** ([layers.json](layers.json), `python scripts/split_layers.py art/stages/hidden-garden`): [03 rear](layers/hg-0-0.03-rear.png) · [04 water](layers/hg-0-0.04-water.png) · [05 play](layers/hg-0-0.05-play.png) · [07 foreground](layers/hg-0-0.07-foreground.png). Everything above the path is one rear layer at scroll 1.0, and the foreground also scrolls at 1.0: rectangles and colours would tear the big tree or the reeds at another speed, so sky/far/mid parallax waits for hand-drawn masks.

| | |
| --- | --- |
| [![Hidden Garden · the bench and the pond](images/hg-0-0-preview.png)](hg-0-0.md)<br>**[Hidden Garden · the bench and the pond](hg-0-0.md)** | |
27 changes: 27 additions & 0 deletions art/stages/hidden-garden/boards.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "Hidden Garden – stage chunks",
"readme": "The prologue, drawn from the approved [Hidden Garden concept](../../locations/hidden-garden-clean.md) as a flat side elevation with its figures removed. One chunk, `hg-0-0` (2160×720): the bench where Dexter sits at the start (x ≈ 190–320), the stone path and the timber jetty (path top y = 441), the end of the jetty where Dexter points (x ≈ 1290–1323), and one wrong patch in the pond's reflection below it – a rusty girder with a ladder that isn't there. Clean only.\n\n**Layers** ([layers.json](layers.json), `python scripts/split_layers.py art/stages/hidden-garden`): [03 rear](layers/hg-0-0.03-rear.png) · [04 water](layers/hg-0-0.04-water.png) · [05 play](layers/hg-0-0.05-play.png) · [07 foreground](layers/hg-0-0.07-foreground.png). Everything above the path is one rear layer at scroll 1.0, and the foreground also scrolls at 1.0: rectangles and colours would tear the big tree or the reeds at another speed, so sky/far/mid parallax waits for hand-drawn masks.",
"model": "gpt-image-2.5-sunburst",
"size": "2160x720",
"style": "FORMAT: a STAGE CONCEPT for a 2D side-scroller explored in all four directions - one wide 2:1 image in strict side view, drawn like an architect's ELEVATION: every path, wall, bed and building runs PARALLEL to the screen from left to right; depth comes only from layers stacked behind each other, never from things receding toward a vanishing point; no path, corridor or bed leads into the distance. The hero is small, about one ninth of the image height. Build real level structure into the scenery: a main route plus at least one higher branch and one lower branch or underground pocket, smooth hills and slopes (some steep enough to slide down), ledges with grabbable edges, something to climb (ladder, vines, scaffold, stairs), a dead end with a small reward glint. DEPTH in clear layers: hazy far background, mid-ground, the play layer, and a dark, out-of-focus foreground of leaves and grass partly covering the bottom edge and corners as if the camera sits behind foliage; reflections where there is water; a few falling leaves. LOOK: detailed hi-bit pixel art, fine 2-pixel grain, the warm palette and light of the style master. TONE: secret horror - calm and pretty first. No text, no logos, no UI.",
"people": "No people, no animals, no plush toys and no characters of any kind: this is an empty stage the game puts its characters into.",
"boards": [
{
"id": "hg-0-0",
"title": "Hidden Garden · the bench and the pond",
"factor": 1,
"keyed": false,
"colours": 256,
"inputs": [
"repo:art/locations/images/hidden-garden-clean.png",
"repo:art/direction/images/style-master-preview.png"
],
"prompt": "Wide side-scrolling stage chunk at 3:1, drawn as an architect's elevation with everything parallel to the screen (no vanishing point, no receding paths): the Hidden Garden pond from the first image, redrawn as a flat side view. Keep its look exactly - late-afternoon autumn light, golden reeds, orange and yellow trees, the misty pine forest behind, a blue sky with small clouds, the big tree in the upper right. Ground: from the left edge a stone-slab path at ground level, its top at about two thirds of the height, runs right onto a timber jetty over the pond; the jetty ends a little right of the middle with two posts - the spot where someone would stand and look down into the water. The calm pond fills the bottom across the whole width and reflects the reeds and trees. ONE patch of the reflection just below the end of the jetty is WRONG: it shows a rusty blue-green riveted girder structure that does not exist above the water. On the right, reeds and a low mossy stone wall close the scene. Along the very bottom edge, a few dark out-of-focus reed silhouettes in the foreground. Remove the two figures of the first image: NO people, NO animals, NO plush toy, nothing standing on the jetty.",
"review": "🟡 Drawn 24 Oct, waiting for Alexander's Design review. The figures of the concept are removed; the bench and the wrong reflection were painted in afterwards with masked edits that change only their own rectangles.",
"edits": [
"bench: masked edit of (190, 392)–(320, 446) – an empty wooden park bench on the path",
"wrong reflection: masked edit of (1080, 505)–(1330, 610) – the water mirrors a rusty girder with a ladder that isn't there"
]
}
]
}
6 changes: 6 additions & 0 deletions art/stages/hidden-garden/chunks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"region": "hidden-garden",
"note": "Chunk ids are grid positions (column-row); art names the plate each state is drawn on.",
"chunks": {"hg-0-0": "hg-0-0"},
"art": {"clean": "images/{chunk}.png"}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions art/stages/hidden-garden/export.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"note": "Layers from split_layers.py (layers.json). Everything scrolls at 1.0 until sky/far/mid get hand-drawn masks.",
"chunks": {"hg-0-0": {"x": 0, "y": 0}},
"layers": {
"03-rear": {"file": "layers/{name}.03-rear.png", "z": 3, "scroll": 1.0},
"04-water": {"file": "layers/{name}.04-water.png", "z": 4, "scroll": 1.0},
"05-play": {"file": "layers/{name}.05-play.png", "z": 5, "scroll": 1.0},
"07-foreground": {"file": "layers/{name}.07-foreground.png", "z": 7, "scroll": 1.0}
},
"states": {"clean": ["03-rear", "04-water", "05-play", "07-foreground"]},
"composed": {"clean": "images/{name}.png"}
}
110 changes: 110 additions & 0 deletions art/stages/hidden-garden/hg-0-0.clean.collision.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"chunk": "hg-0-0",
"state": "clean",
"size": [
2160,
720
],
"walk": [
[
[
0,
441
],
[
1323,
441
]
]
],
"slide": [],
"oneWay": [],
"climb": [],
"solid": [
{
"x": 0,
"y": 0,
"w": 8,
"h": 720
},
{
"x": 1326,
"y": 300,
"w": 24,
"h": 141
}
],
"noGo": [
{
"x": 0,
"y": 478,
"w": 2160,
"h": 242
}
],
"hazard": [],
"interact": [
{
"id": "pond-edge",
"kind": "anomaly",
"x": 1250,
"y": 365,
"w": 70,
"h": 76,
"note": "Dexter points at the ground here, then shoves the hero into the pond (M3-S3 #50, M3-S4 #51)"
},
{
"id": "to-rusty-creek",
"kind": "chunk-exit",
"x": 1250,
"y": 365,
"w": 70,
"h": 76,
"note": "the crossing: after the shove the hero lands in clean Rusty Creek (rc-0-0)"
},
{
"id": "dexter-waypoint-1",
"kind": "dexter-waypoint",
"x": 215,
"y": 365,
"w": 80,
"h": 76,
"note": "the bench: Dexter waits here; walking up makes him hop off"
},
{
"id": "dexter-waypoint-2",
"kind": "dexter-waypoint",
"x": 680,
"y": 365,
"w": 80,
"h": 76,
"note": "mid-path: Dexter hops ahead and beckons"
},
{
"id": "dexter-waypoint-3",
"kind": "dexter-waypoint",
"x": 1150,
"y": 365,
"w": 80,
"h": 76,
"note": "the jetty: Dexter stops and points at the water"
}
],
"spawn": [
{
"id": "player",
"kind": "player",
"x": 90,
"y": 441
},
{
"id": "dexter-bench",
"kind": "dexter",
"x": 255,
"y": 421,
"note": "Dexter sits on the bench at the start"
}
],
"ledge": [],
"glideLift": []
}
16 changes: 16 additions & 0 deletions art/stages/hidden-garden/hg-0-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Hidden Garden · the bench and the pond

![Hidden Garden · the bench and the pond](images/hg-0-0-preview.png)

**Review:** 🟡 Drawn 24 Oct, waiting for Alexander's Design review. The figures of the concept are removed; the bench and the wrong reflection were painted in afterwards with masked edits that change only their own rectangles.

## Brief

Wide side-scrolling stage chunk at 3:1, drawn as an architect's elevation with everything parallel to the screen (no vanishing point, no receding paths): the Hidden Garden pond from the first image, redrawn as a flat side view. Keep its look exactly - late-afternoon autumn light, golden reeds, orange and yellow trees, the misty pine forest behind, a blue sky with small clouds, the big tree in the upper right. Ground: from the left edge a stone-slab path at ground level, its top at about two thirds of the height, runs right onto a timber jetty over the pond; the jetty ends a little right of the middle with two posts - the spot where someone would stand and look down into the water. The calm pond fills the bottom across the whole width and reflects the reeds and trees. ONE patch of the reflection just below the end of the jetty is WRONG: it shows a rusty blue-green riveted girder structure that does not exist above the water. On the right, reeds and a low mossy stone wall close the scene. Along the very bottom edge, a few dark out-of-focus reed silhouettes in the foreground. Remove the two figures of the first image: NO people, NO animals, NO plush toy, nothing standing on the jetty.

## Inputs

- [hidden-garden-clean.png](../../locations/images/hidden-garden-clean.png)
- [style-master-preview.png](../../direction/images/style-master-preview.png)

Model `gpt-image-2.5-sunburst` · pixel factor 1 · source image `images/hg-0-0.png` · rebuild: `python scripts/make_boards.py draw --config art/stages/hidden-garden/boards.json --redo hg-0-0`
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added art/stages/hidden-garden/images/hg-0-0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
130 changes: 130 additions & 0 deletions art/stages/hidden-garden/layers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{
"note": "Rules run in order; the last rule that claims a pixel wins. Everything above the path stays one rear layer (scroll 1.0): rectangles would tear the big tree from its trunk at another scroll speed, so sky/far/mid parallax waits for hand-drawn masks.",
"chunks": {
"hg-0-0": {
"states": {
"clean": "images/hg-0-0.png"
},
"default": "03-rear",
"rules": [
{
"layer": "04-water",
"rect": [
0,
478,
2160,
720
]
},
{
"layer": "05-play",
"rect": [
140,
441,
1790,
478
]
},
{
"layer": "05-play",
"rect": [
1026,
392,
1323,
478
]
},
{
"layer": "07-foreground",
"colour": [
40,
14,
5
],
"tolerance": 32,
"rect": [
0,
560,
330,
720
]
},
{
"layer": "07-foreground",
"colour": [
80,
38,
10
],
"tolerance": 28,
"rect": [
0,
560,
330,
720
]
},
{
"layer": "07-foreground",
"colour": [
40,
14,
5
],
"tolerance": 32,
"rect": [
1380,
560,
2160,
720
]
},
{
"layer": "07-foreground",
"colour": [
80,
38,
10
],
"tolerance": 28,
"rect": [
1380,
560,
2160,
720
]
},
{
"layer": "07-foreground",
"colour": [
40,
14,
5
],
"tolerance": 32,
"rect": [
330,
690,
1380,
720
]
},
{
"layer": "07-foreground",
"colour": [
80,
38,
10
],
"tolerance": 28,
"rect": [
330,
690,
1380,
720
]
}
]
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions art/stages/rusty-creek/export.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"note": "Draw order follows creek_layers.py compose(): the plates are soft and blend, so the water is drawn last. z names the docs/04 role; loaders draw in list order.",
"chunks": {
"rc-0-0": {"x": 0, "y": 0, "name": "left"},
"rc-1-0": {"x": 1, "y": 0, "name": "center"},
"rc-2-0": {"x": 2, "y": 0, "name": "right"}
},
"layers": {
"01-distance": {"file": "images/01-distance-{name}.png", "z": 1, "scroll": 0.2},
"03-bank": {"file": "images/03-bank-{name}.png", "z": 2, "scroll": 1.0},
"02-supports": {"file": "images/02-supports-{name}.png", "z": 3, "scroll": 1.0},
"clean-architecture": {"file": "images/clean-architecture-{name}.png", "z": 3, "scroll": 1.0},
"05-traversal": {"file": "images/05-traversal-{name}.png", "z": 5, "scroll": 1.0},
"06-near-rails": {"file": "images/06-near-rails-{name}.png", "z": 6, "scroll": 1.1},
"07-foliage": {"file": "images/07-foliage-{name}.png", "z": 7, "scroll": 1.15},
"04-water": {"file": "images/04-water-{name}.png", "z": 4, "scroll": 1.0}
},
"states": {
"anomaly": ["01-distance", "03-bank", "02-supports", "05-traversal", "06-near-rails", "07-foliage", "04-water"],
"clean": ["01-distance", "03-bank", "clean-architecture", "06-near-rails", "07-foliage", "04-water"]
},
"composed": {"anomaly": "images/after-{name}.png", "clean": "images/before-{name}.png"},
"aliases": "media-sources.json"
}
2 changes: 1 addition & 1 deletion docs/07-ASSET-MANIFEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Frame lists approved as they are (A14).
| --- | --- | --- |
| Rusty Creek | 3 chunks × 7 layers, clean + anomaly states, route graph | ✅ art · ⬜ collision · ⬜ foreground-blur + particle layers |
| Stage concepts (6 regions × clean/anomaly) | 2176×1088 concepts with up/down routes ([art/locations](../art/locations/README.md)) | 🟡 in review |
| Hidden Garden (prologue) | 2–3 chunks (about 3 minutes of play), layer stack + collision, from its stage concept and Lex's layout | ⬜ |
| Hidden Garden (prologue) | 1 chunk `hg-0-0` ([art/stages/hidden-garden](../art/stages/hidden-garden/README.md)): bench, path, jetty, the wrong reflection; layers 03/04/05/07. A second chunk waits for seam repair | 🟡 in review · ⬜ collision |
| Jenny's arena | right chunk of Rusty Creek (boss clearing) | ✅ art · ⬜ collision |

## Audio (to source during the jam)
Expand Down
1 change: 1 addition & 0 deletions docs/09-ART-PIPELINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ python scripts/creek_layers.py [--build] # Rusty Creek
python scripts/collision_check.py [--overlay] # collision: schema, reach, overlays
python scripts/stage_art.py prepare --config art/stages/rusty-creek/stage.json --out tmp/stage-art/next --band 512
python scripts/split_layers.py art/stages/<region> [--check] # composed chunk -> z0–z7 layers, exact
python scripts/export_stage.py [--verify] # art/stages -> game stage.json + plates (generated)
python scripts/navigation.py && python scripts/check_docs.py
```

Expand Down
2 changes: 1 addition & 1 deletion docs/13-PRODUCTION-PIPELINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ Lane B codes against these from day one, with placeholders; lane A fills them wi
| --- | --- | --- | --- |
| Atlas | `game/public/assets/sprites/<board>.png` + `.json` | Phaser JSON hash; frame names `<animation>-<nn>` from `00`, one cell size per board; pivot at the feet (0.5, 1) | `export_atlas.py` (A) → loader (B) |
| Animations | `game/public/assets/sprites/<board>.anims.json` | `{"walk": {"frames": 8, "fps": 12, "loop": true}, …}` – names and counts as in docs/07 | `export_atlas.py` (A) → state machine (B) |
| Stage manifest | `game/public/assets/stages/<region>/stage.json` | chunk ids with grid x/y, per chunk the layer files z0–z7 for each state, scroll factors | stage export (A) → loader (B) |
| Stage manifest | `game/public/assets/stages/<region>/stage.json` (generated by `scripts/export_stage.py`, not committed) | `{"region", "chunkSize": [2160, 720], "chunks": [{"id": "rc-0-0", "x": 0, "y": 0, "states": {"anomaly": {"layers": [{"id", "z", "scroll", "file"}], "collision": "rc-0-0.anomaly.collision.json"}}}]}`. Draw the layers **in list order** (Rusty Creek's soft water goes last); `z` names the docs/04 role. Files sit next to the manifest | stage export (A) → loader (B) |
| Collision | `art/stages/<region>/<chunk>.<state>.collision.json`, chunk ids `<prefix>-<column>-<row>` | above; checked by `collision_check.py` | A (Tiled + converter, or by hand) → loader (B) |
| Game events | `game/src/core/events.ts` | typed events: `enemy-defeated`, `player-hit`, `player-died`, `region-turned`, `boss-defeated`, `save` | combat and enemies (B) emit → story and UI (A) listen |
| Placeholder sizes | – | hero 28×76 body in an 80 px frame; Dexter 20 px; rover ≈ 25 px; crab ≈ 40 px; drone ≈ 45 px; Jenny ≈ 200×70 | docs/04 scale table |
Expand Down
Loading
Loading