diff --git a/projects/kissaten_yugure/art/palette.png b/projects/kissaten_yugure/art/palette.png new file mode 100644 index 0000000..4d4dce7 Binary files /dev/null and b/projects/kissaten_yugure/art/palette.png differ diff --git a/projects/kissaten_yugure/art/palette_ref.png b/projects/kissaten_yugure/art/palette_ref.png new file mode 100644 index 0000000..937b0b6 Binary files /dev/null and b/projects/kissaten_yugure/art/palette_ref.png differ diff --git a/projects/kissaten_yugure/docs/ART.md b/projects/kissaten_yugure/docs/ART.md new file mode 100644 index 0000000..7d92560 --- /dev/null +++ b/projects/kissaten_yugure/docs/ART.md @@ -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 8–11 are sky. Slots 4–7 are wood and warm interior.** Nothing else may +use 8–11. + +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=16–148** is the shop scene. +- Bottom **64px** is the dialogue window (drawn over) — keep it empty/dark. +- Window on the **left** (~x16–88), showing dusk sky in slots 8–11 only. +- Door on the **right** (~x208–244). +- 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 8–11.** 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. diff --git a/projects/kissaten_yugure/docs/PLAN.md b/projects/kissaten_yugure/docs/PLAN.md index d49f9b9..9d71a71 100644 --- a/projects/kissaten_yugure/docs/PLAN.md +++ b/projects/kissaten_yugure/docs/PLAN.md @@ -180,19 +180,14 @@ The real background bitmap on the palette-slot layout already reserved in code (sky 8–11, wood/warm 4–7), plus 12 portraits (4 characters × 3 expressions). Retire the placeholder `HMMV` rectangles. -**Requires — from you:** *(this is the milestone with real lead time — start -it early, see §5)* -- **Who makes the art.** You, a commission, or an AI-assisted pipeline like - the music one. This answer determines whether M6 is a week or a quarter. -- **One background bitmap**, 256×212, 16 colors. -- **12 portraits**, 48×48, three expressions each (neutral / happy / - troubled) for the four regulars. -- **Critically: the palette spec goes to the artist *before* they draw.** Sky - tones must live in slots 8–11 and wood/warm tones in 4–7, because that - layout is what makes M7's seasons free. Art drawn in open color and - quantized afterwards will land in the wrong slots and silently destroy the - seasonal system. I can generate the exact palette table and a reference - swatch image to hand over. +**Requires — from you:** generated in **PixelLab** from the prompts in +`ART.md` — one 256×212 background and 12 portraits (48×48, three expressions +× four regulars), returned as PNGs in `art/`. + +The palette spec and the sky/wood slot rule are written up in `ART.md` §1, +with machine- and human-readable references at `art/palette.png` and +`art/palette_ref.png`. **That rule is the whole of M7 riding on one +constraint**, and a generator will not respect it unprompted. **Requires — in place:** - A PNG → SC5 conversion path. `projects/mazegame` already has working @@ -525,7 +520,7 @@ milestone arrives. | 5 | M3 | ~~Aki's six beats~~ | ✅ drafted — all four arcs are in `SCRIPT.md`, awaiting your edit | | 6 | M3 | Scratch portrait for Aki | Crude is fine, but *something* — the test needs a face | | 7 | M3 | Item list at slice stage | Coffee + cream soda only | -| 8 | **M6 — lead time** | **Who makes the art** | Decide now, not at M6; it's the only external dependency | +| 8 | M6 | ~~Who makes the art~~ → **PixelLab, from my prompts** | ✅ resolved. Prompts, palette spec and return format in `ART.md`; palette reference images in `art/` | | 9 | M4 | Scene schema sign-off | Ten-minute review, saves a rewrite | | 10 | M4 | String IDs for future JP text | Yes — nearly free now, expensive later | | 11 | M5 | Arrival weights | React to a table I propose | @@ -545,8 +540,8 @@ are deliberately *not* being decided now. They only bite at M10, and every one of them is easier to judge with real save content on screen than in the abstract. Don't let them pull scope forward. -Of the live items, **8 is the one that wants answering today** — the art has -external lead time and everything else can be worked around. +With 8 resolved, nothing on the live list is externally blocked — the +remaining items are all things I can propose and you can react to. ## 9. Immediate next actions @@ -558,7 +553,7 @@ external lead time and everything else can be worked around. 3. ⬜ **M3 vertical slice** — Aki's first six beats, hardcoded, with a scratch portrait. The next real milestone, and the one that decides whether the game works (§2, M3). -4. ⬜ **Start the portrait question** (§5) — still the only item with external - lead time, and now the longest pole by some distance. +4. ⬜ **Generate Aki's three portraits** from the prompts in `ART.md`, so M3 + can be judged against a real face rather than a brown rectangle. -3 and 4 are independent; 4 can start today and should. +3 and 4 are independent, and 4 unblocks the honest version of 3.