Add art brief and palette references for the PixelLab pipeline

Resolves decision 8: art is generated in PixelLab from written prompts.
docs/ART.md carries the palette spec, the sky/wood slot rule, per-asset
sizes and return format, and prompts for Aki (needed for M3), the rest of
the cast, and the shop background.

art/palette.png (16x1, one pixel per entry) and art/palette_ref.png
(512x64 swatch strip) are generated from g_Palette so the generator and
the build cannot drift apart.

Flags a constraint the palette had hidden: only one literal skin entry, so
portraits use 6 -> 14 -> 4 as a hue-compatible skin ramp.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 22:34:05 +02:00
co-authored by Claude Opus 5
parent 97eebbaefc
commit 25a098e6af
4 changed files with 190 additions and 19 deletions
+176
View File
@@ -0,0 +1,176 @@
# Kissaten Yūgure — Art brief
Pipeline: **you generate in PixelLab from the prompts below, drop the PNGs in
`art/`, and I convert them to SCREEN 5 data.** I'll write the converter
(`tools/convert_art.py`) once the first real images land — there's working
precedent in `projects/mazegame/convert_screens.py`.
---
## 1. The palette — read this before generating anything
Everything in the game shares **one 16-colour palette**. It is already in
`kissaten.c` as `g_Palette` and is what the current build renders with.
- `art/palette.png` — 16×1 px, one pixel per entry. Machine-readable; use it
wherever PixelLab accepts a palette image.
- `art/palette_ref.png` — 512×64 swatch strip, same order, for eyeballing.
| # | Hex | Role | Notes |
|---|---|---|---|
| 0 | `#000000` | transparent | **Never paint with this.** It is the transparent index. |
| 1 | `#242424` | outline | near-black; outlines, dark hair |
| 2 | `#492424` | dark wood | deep shadow, dark brown hair |
| 3 | `#924924` | mid wood | wall panels, doors, deep skin shadow |
| 4 | `#B66D49` | light wood | counter top, **skin shadow** |
| 5 | `#FFB649` | lamp glow | warm light |
| 6 | `#FFDB92` | cream | glassware, **skin highlight** |
| 7 | `#6D4949` | muted wall | upper wall, muted cloth |
| 8 | `#492492` | dusk deep | **sky only** |
| 9 | `#9249B6` | dusk violet | **sky only** |
| 10 | `#DB6D6D` | dusk rose | **sky only** |
| 11 | `#FF9249` | horizon amber | **sky only** |
| 12 | `#6D2400` | coffee | coffee, dark red-brown cloth |
| 13 | `#496DB6` | coat blue | uniforms, coats |
| 14 | `#FFB692` | skin | **skin base** |
| 15 | `#FFFFDB` | warm white | highlights, cup rims, eye whites |
### The one non-negotiable rule
**Slots 811 are sky. Slots 47 are wood and warm interior.** Nothing else may
use 811.
This is what makes seasons and time-of-day free: the background bitmap is
authored once, and each season/hour is a 32-byte palette swap. If a character's
jacket is painted in slot 9, that jacket changes colour every time the sun
moves. Getting this wrong is not a cosmetic issue — it silently destroys the
whole seasonal system, and you don't find out until M7.
### Skin, specifically
There is only one literal "skin" entry, which is too thin for a face. Use
these three as a ramp — they're hue-compatible:
- highlight `#FFDB92` (6) → base `#FFB692` (14) → shadow `#B66D49` (4)
- deepest shadow / hair: `#924924` (3), `#492424` (2), `#242424` (1)
---
## 2. What I need back
| Asset | Size | Count |
|---|---|---|
| Character portrait | **48×48** | 3 per character (neutral / happy / troubled) |
| Shop background | **256×212** | 1 |
| Customer sprite | **16×16** | 2 layers per character (fill + outline) |
**PNG, generated natively at the target size — do not downscale a larger
image.** Downscaling pixel art produces half-pixels and anti-aliased edges
that cannot be quantised cleanly.
No anti-aliasing, no gradients, no dithering unless it's deliberate hard
checkerboard. If PixelLab can be constrained to the 16 colours, do that; if
not, generate close and I'll quantise — but the sky/wood slot rule above
still has to hold visually or the quantiser can't fix it.
**48×48 is very small** — roughly 6 pixels of eye. Faces need a strong
silhouette and simplified features. Detail that reads at 200×200 will turn to
mud. If a generation looks great zoomed out and illegible at 1:1, it's wrong.
---
## 3. Prompts — Aki (needed now, for M3)
Hoshino Aki, 17, studying for Tokyo entrance exams, cream soda drinker.
Character notes in `SCRIPT.md` §1. Written as a girl there; that's one word to
change if you'd rather — the dialogue beats themselves use no gendered
pronouns.
**Common style stem** — prepend to all three:
> 48x48 pixel art portrait, 1987 Japanese anime style as drawn for MSX2 or
> PC-88 games, head and shoulders, three-quarter view, hard-edged pixels, no
> anti-aliasing, limited 16 colour palette of warm browns oranges and creams,
> flat cel shading, dark navy school uniform, simple readable silhouette,
> plain dark background
**Aki — neutral**
> ...17 year old Japanese high school student, straight dark bob-length hair,
> tired but polite expression, calm eyes, slight shadows under the eyes,
> looking slightly off to one side
**Aki — happy**
> ...17 year old Japanese high school student, straight dark bob-length hair,
> small genuine smile, eyes softened and slightly narrowed, faint blush,
> looking toward the viewer
**Aki — troubled**
> ...17 year old Japanese high school student, straight dark bob-length hair,
> eyes cast downward, faint frown, tense mouth, weary
---
## 4. Prompts — the rest of the cast (M8, not urgent)
Same style stem, swapping the uniform line.
**Ōta-san** — retired stationmaster, ~70, black coffee, punctual.
> elderly Japanese man in his seventies, close-cropped grey hair, deeply
> lined face, upright bearing, plain dark jacket buttoned to the collar
- *neutral:* composed, formal · *happy:* faint dignified smile, eyes crinkled
- *troubled:* jaw set, looking past the viewer
**Fujimoto** — manga artist, ~30, exhausted, funny about it.
> Japanese manga artist in their thirties, messy shoulder-length hair, heavy
> shadows under the eyes, round glasses, rumpled shirt with sleeves pushed up
- *neutral:* wired, sleepless · *happy:* crooked grin, animated
- *troubled:* hollow stare, hand near face
**Nakajima-san** — widow, ~65, orders two coffees.
> Japanese woman in her mid-sixties, silver hair pinned back neatly, soft
> composed face, high-collared blouse under a plain cardigan, small pearl
> earrings
- *neutral:* serene, self-possessed · *happy:* warm gentle smile
- *troubled:* distant, looking at something not in the room
---
## 5. Prompt — the shop background (M6, longest lead time)
256×212. This one carries the game's whole look and is the hardest to redo,
so it's worth several attempts.
Composition is fixed by the code — see `DESIGN.md` §4 and `DrawScene()`:
- Top **16px** is the status bar (drawn over) — keep it empty/dark.
- **y=16148** is the shop scene.
- Bottom **64px** is the dialogue window (drawn over) — keep it empty/dark.
- Window on the **left** (~x1688), showing dusk sky in slots 811 only.
- Door on the **right** (~x208244).
- Counter running horizontally at **y≈98**, its top edge level.
- Hanging lamp above the counter, centre.
- Siphon coffee rig sits on the counter left of centre — I can keep drawing
this procedurally if it's easier to leave out.
> 256x212 pixel art interior of a small 1987 Japanese kissaten coffee shop at
> dusk, viewed straight on, static single-screen game background, wooden
> counter running across the lower third, tall window on the left showing a
> violet and amber dusk sky, wooden door on the right, hanging lamp with warm
> glow above the counter, wood panelling, shelves with glassware, cosy and
> quiet, 1987 MSX2 game art, hard-edged pixels, no anti-aliasing, flat cel
> shading, warm brown and orange interior with the sky in violet and amber
**The sky through that window must use only slots 811.** Everything else in
the room must avoid them. That's the whole seasonal system riding on one rule.
---
## 6. Sprites (M6)
16×16, two layers per customer: a **fill** layer and an **outline** layer that
is the same silhouette dilated by one pixel, drawn behind. Sprite mode 2, so
each layer is a single colour — these are shapes, not shaded art. Current
placeholders are in `kissaten.c` as `g_SprCustFill` / `g_SprCustLine`.
Worth doing by hand rather than generating; a 16×16 single-colour silhouette
is faster to draw than to prompt for.