not-tonight/docs/SPACES.md
type-two ae036d9d0e One camera for the whole tileset: nine chunky props re-meshed and ortho-rendered
9/9 through flux product shot -> trellis2_mlx -> glb_to_sprite, unattended.
Rake corrected after the first pass: tall objects need a STEEPER angle (76), not
a shallower one — an arcade at 55 is a front-on slab. Re-angled from the meshes
already on disk, no re-generation, which is the point of keeping the GLB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 14:55:19 +10:00

11 KiB
Raw Blame History

NOT TONIGHT — Spaces Plan

How the game's two spaces grow from readable-but-abstract into places, using the fleet's asset factories. Written 2026-07-20. Code contract: everything lands behind data tables (venueMap.PROPS / LIGHTS) and a sprite drop-in convention — generated art replaces placeholders with zero code changes.

1. Design principles

  1. Darkness stays the mechanic. Props read as silhouettes in ambient dark and resolve under the torch. Nothing may make the room bright enough to scan from the doorway.
  2. Navigate by light signature. Each zone owns a colour of light, so the player orients by glow before geometry: bar = warm amber · dance floor = pulsing pink (on the actual beat) · DJ booth = deep blue · toilets = flickering green fluoro · smoking yard = cool rain-blue spill · entry/exit = venue pink. The torch is white; UV is purple. No other light sources.
  3. Props are data. PropDef { kind, tile pos, footprint, emissive? } — the renderer prefers a generated texture (gen:prop:<kind>) and falls back to a procedural placeholder, so the game is complete TONIGHT and gets prettier as art lands.
  4. Spaces anticipate the role ladder (design §6): the bar interior is laid out for a future bartender shift, the DJ booth for the DJ shift, the glassie station and smoking yard for floor loops that already have lanes speccing them.

2. The venue floor (80×45 tiles, one room + pockets)

┌──────────────────────────────────────────────────────────────────┐
│ N  ═ BAR ══════════ back-shelf glow          ┌─ DUNNIES ────────┐│
│    taps · till · glasses                     │ s1 s2 s3 s4      ││
│    ○○○○○○ stools                             │ sinks + mirror   ││
│                                              └───door───────────┘│
│ W                                                                 │
│ ┈entry┈  ┌ DANCE FLOOR (pulsing grid) ┐   ╔═ DJ BOOTH ╗    booths│
│ corridor │ speaker · · · · · speaker  │   ║ decks+mixer║        E│
│ posters  │  · · · disco ball · · ·    │   ║ (sealed)   ║   booths│
│ cloak    │ speaker · · · · · speaker  │   ╚════════════╝        │
│ glassie  └───────────────────────────┘                    booths│
│ station                                                          │
│    ▓ SMOKING YARD (open sky, rain) ▓   tables+candles     S     │
└────────▓ fence · butt bin ▓──────────────────────────────────────┘

Zone-by-zone (tile coords in venueMap.ts):

Zone What's there (props) Light signature Future role hook
Bar (north run) back-bar shelf (emissive), 3 beer taps, till, glass stacks steady amber pools along the shelf Bartender shift: the serving lane between bar tiles and shelf is already unwalkable-to-patrons
Dance floor (centre) 4 corner speaker stacks, disco ball (centre), floor grid cells pink grid cells pulse ON beat:tick; ball throws a slow-rotating glint DJ role reads crowd here
DJ booth (east of dance, sealed box facing the floor) 2 decks + mixer (from the 90sDJsim gear GLBs!), booth monitor, lamp deep blue wash + VU flicker The DJ shift's playable pocket
Booths (south + east walls) table per booth pair, candle tiny warm candle pools
Dunnies (NE walled room) sink row + mirror on west wall, hand dryer green fluoro, FLICKERS (torch almost redundant inside — deliberate)
Smoking yard (SW walled pocket, open sky) butt bin, milk crate seats, fence cool blue outdoor spill + rain particles INSIDE the yard FLOOR2's smoking loop (specced)
Entry corridor (west) poster wall (3 art slots — MODELBEAST posters!), cloakroom window, stamp podium venue-pink spill from the door UV re-entry checks happen here
Glassie station (bar's west end alcove) glass racks, tub trolley dim amber Glassie role's home base

Sim impact: walkability only changes where NEW walls go (DJ booth box, yard fence, sink row). All existing anchors keep working; reachability is asserted in tests. The yard gets a smoke anchor upgrade so wanderers actually go out for one.

3. The door street (640×360 tableau)

Already reads well. Two upgrades, both drop-in images (no layout change):

  1. Backdrop plate behind the existing rects: one wide pixel-art street wall (brick, posters, grime) — swaps in as gen:street:backdrop when generated.
  2. Kebab shop interior glow card in its window + rotating poster art in two street frames (same poster slots as the entry corridor).

4. The sprite drop-in contract (how John's art lands)

  • Drop processed PNGs in public/props/ named <kind>.png and list them in public/props/manifest.json ({"props": ["deck", "speaker", ...]}).
  • The floor loads the manifest at boot; anything listed replaces its placeholder (texture key gen:prop:<kind>). Missing = placeholder. No code changes.
  • tools/props_import.py (PIL, runs anywhere with python3+PIL — ultra has it) takes raw generated images → target pixel size + palette quantise + transparent background → writes public/props/ + updates the manifest: python3 tools/props_import.py incoming/deck_raw.png deck
  • Target sizes are in the script (TARGETS): hero props 4864 px, furniture 2432 px, small items 16 px. It refuses unknown kinds so typos can't ship.

5. GENERATION QUEUE — John's list (in priority order)

Pipelines: [MB] = MODELBEAST flux_local (params given) → drop raw output in art_incoming/, run the import script (or hand me the raws — either works). [GLB] = Blender ortho prerender of an existing fleet mesh (camera: orthographic, top-down 90° for floor props / front 0° for the street, transparent film, ~512px, neutral even lighting) → same import path.

# Item (kind) Pipeline & source Notes
1 deck [GLB] ultra:~/Documents/90sDJsim/web/world/models/gear/deck_t3_technics_sl_1200mk2.glb, top-down The hero. One render serves both booth decks
2 mixer [GLB] same dir, mixer.glb (or the urei once landed), top-down Sits between the decks
3 speaker [GLB] 90sDJsim models/props/ has boombox/speaker meshes; else [MB] prompt: "top-down view of a large black PA speaker stack, pixel art game sprite, dark background, viewed directly from above" 512×512 seed 4210 4 placements
4 discoball [MB] "mirrored disco ball seen directly from above, glinting, pixel art sprite, black background" 512×512 seed 4211 Centre of dance floor
5 barShelf [MB] "top-down bar back-shelf with glowing bottles rows, amber light, pixel art sprite, dark" 1024×256 seed 4212 Emissive — the amber source
6 taps [MB] "row of three beer taps on a bar counter viewed from above, pixel art, dark bg" 256×256 seed 4213
7 boothTable [MB] "small round pub table with two drinks seen from directly above, pixel art, dark bg" 256×256 seed 4214 6 placements
8 sink [MB] "public bathroom sink row with mirror viewed from above, green fluorescent light, pixel art, dark" 512×256 seed 4215
9 buttBin + crate [MB] one sheet: "outdoor smoking area props: cigarette butt bin and milk crate, top-down pixel art, dark bg" 512×256 seed 4216 Yard dressing
10 poster1..3 [MB] three runs: "grimy nightclub gig poster, 90s Australian pub rock / techno rave / missing cat, pixel art, portrait" 256×384 seeds 4217-19 FRONT view (posters hang on walls) — used at door + corridor
11 street:backdrop [MB] "wide pixel art night street wall: dark brick, torn posters, graffiti, neon reflections, rain, front-on orthographic, game background" 1600×440 seed 4220 The door scene plate. Biggest single visual win
12 cloak / glassRack [MB] "cloakroom window with hanging jackets / metal glass rack with stacked pint glasses, top-down pixel art, dark" 256×256 seeds 4221-22 Corridor + glassie station
13 arcade [GLB] m3ultra:~/Documents/procity/pipeline/_normalized/procity_fit_arcade_cabinet_01.glb, top-down Corner easter egg near entry

Ambition tier (later, not blocking): pre-rendered patron sprite sheets from the modular character kit + RIGROOM clips (Searching_Pockets, boxing pack, Leaning_Idle02_Smoking, zombie stagger for maggots) — replaces the procedural dolls entirely per docs/ASSETS.md §2. Wants its own session to set the palette/density once.

(flux params for all [MB] jobs: model flux2-klein-4b, steps 4; put "no text, no lettering" in every prompt EXCEPT the posters, where mangled text reads as authentic gig-poster grot.)

Prop pipeline — settled 2026-07-22 (A/B'd, not guessed)

Two routes, both free and unlimited on MODELBEAST. Pick by object, not by habit.

[MB] flux directflux_localtools/props_import.py. Fast (~9s). Use for FLAT things: posters, decals, graffiti, signage, floor markings.

[GLB] TRELLIS → Blenderflux_local (product shot) → trellis2_mlx (asset_id is a TOP-LEVEL job field, NOT inside params) → tools/glb_to_sprite.py <mesh.glb> <kind> → sprite + manifest, headless, no GUI. Use for objects with real VOLUME: tables, fridges, machines, furniture.

Why the split, from the A/B (same pool table, both routes): flux picks its own camera every generation — the same prompt style gave a perfectly top-down urinal and a front-on fridge in one batch, and mismatched camera angles never read as one room. The mesh route renders every prop from one fixed ortho camera, and TRELLIS carries detail flux flattens: worn felt, real pockets, rails and legs, clean alpha.

RAKE by object HEIGHT — and I had this backwards first time. Low and wide (pool table, booth table, crate): 60°. Tall (arcade, fridge, speaker, anything standing): ~76°. The instinct to lower the rake for tall objects "so you see more face" is wrong — a tall object already shows nothing but face; it needs to be steeper to read as a floor prop at all. A speaker at 55° is a featureless black slab.

Judge sprites at SHIP size, not render size. A 512px render of a fridge from above looks ambiguous; the same sprite at 32x32 under the game's own point light reads fine, because the venue's LIGHTS do half the identifying work (the fridges carry a cyan glow, the arcade a flickering blue). Do not re-roll a prop off the back of the big preview.

The old guidance, kept because it is still true for low objects: The venue's props are three-quarter top-down, not straight down. Re-rolled from directly overhead, a bar fridge is a grey rectangle — physically correct and visually dead, because the glowing bottles that say "fridge" are on its front. 60° keeps the top surface dominant while leaving enough face to identify the object at 32px.