# The Settled Reach — Placeholder Art Specification v0.1 **Version:** v0.1 (Sprint 12) **Author:** Araminta (Visual Designer) **Date:** 2026-02-19 **Status:** Active — unblocks #133 (placeholder art pipeline) **Cross-reference:** `docs/design/visual-grammar-v01.md` (visual grammar — this document derives from it) This specification defines the technical requirements for placeholder art assets. v0.1 target: **zero image files**. All placeholder art is procedural — colored rectangles, styled text, shader overlays. This spec defines what the placeholder pipeline must produce so it can be swapped for real art without architectural changes. --- ## 1. Grid and Tile Dimensions ### 1.1 Dual-Scale Grid (D-066) | Scale | Unit | Size | Used by | |-------|------|------|---------| | Simulation tile | 0.5m per tile | 32×32px (internal) | Server: movement, LOS, pathfinding, occupancy | | Visual tile | 1m per tile = 2×2 sim tiles | **64×64px at runtime** | Client: all art authoring, tile placement | **Author all art at 1m visual tile scale = 64×64px per tile.** The simulation subdivides automatically. The pipeline does not need to know about 32×32 sim tiles. ### 1.2 Runtime Resolution | Context | Value | |---------|-------| | Visual tile size | 64×64 px | | Game base resolution | 1920×1080 (1080p) | | Godot camera | Orthographic, no DPI scaling applied to tile grid | | Camera zoom | 1:1 at 1080p (1 viewport pixel = 1 art pixel) | Do not target Retina/HiDPI resolutions with placeholder art — that's a production phase concern. --- ## 2. Tile Art Requirements ### 2.1 Structural Tiles (Floor, Wall, Door) All structural tiles are **solid colored rectangles** in v0.1. No texture, no grain. Color palette from visual grammar §1.2–1.4. | Tile type | Size | Color | Outline | |-----------|------|-------|---------| | Floor — Logistics Hub | 64×64 px | `#1a1e24` | None | | Floor — Bar | 64×64 px | `#1e1912` | None | | Floor — Corridor | 64×64 px | `#181818` | None | | Wall face | 64×64 px | Zone wall face color (see visual grammar §1) | None (outlines added via LightOccluder2D geometry) | | Wall top | 64×64 px | Zone wall top color (see visual grammar §1) | None. Rendered on z-layer 4 at ~70% opacity (D-049). Creates overhead occlusion. | | Door (closed) | 64×64 px | Same as wall face, 4px lighter | 1px `#333340` | | Door (open) | 64×64 px | Same as floor | 1px `#333340` threshold outline baked into the sprite at the doorway edge | | Transition strip | 64×64 px | 50/50 horizontal split between adjacent zone floor colors | None. Procedurally generated per zone boundary — not a hand-authored asset. | **Transition strips** (zone boundary tiles): generated procedurally at runtime as a horizontal 50/50 split between the two adjacent zone floor colors. No hand-authored asset required — the pipeline produces these from zone adjacency data. If a simple split reads poorly, upgrade to a 4-pixel dithered blend. ### 2.2 Object Tiles (Furniture, Equipment) Objects are **tinted rectangles with a text label** in v0.1. Label identifies the object type. | Object category | Size (visual tiles) | Fill color | Outline | Label | |----------------|--------------------|----|---------|-------| | Small item | 1×1 | `#8b8ba0` at 60% opacity | 1px `#333340` | Object name, 10px Michroma | | Furniture | 1×1 or 2×1 | `#8b8ba0` at 70% opacity | 1px `#333340` | Object name, 10px Michroma | | Large furniture | 2×1 or 3×1 | `#8b8ba0` at 70% opacity | 1px `#333340` | Object name, 10px Michroma | | Terminal | 1×1 | `#4a5a7a` at 80% opacity | 1px `#4a9ebb` | "TERMINAL", 10px Michroma | | Cargo crate | 1×1 or 2×1 | `#6a5a3a` at 70% opacity | 1px `#8b7a5a` | "CARGO", 10px Michroma | Label placement: centered in the object rectangle. If the object is too small for a label, omit it. Legibility over completeness. --- ## 3. Entity Sprite Requirements ### 3.1 Sprite Canvas and Art Area | Property | Value | |----------|-------| | Canvas size | 64×64 px (= 2×2 sim tiles, 1×1 visual tile footprint) | | Art area | 24×32 px, centered within canvas | | Dead space | 20px left, 20px right, 16px top, 16px bottom | | Outline | 2px in D-033 relationship color | Dead space is intentional — it provides clearance so entities don't visually merge when sharing adjacent tiles. ### 3.2 Placeholder Entity Shape In v0.1, all entities are **tinted rectangle + outline + name label**: - Rectangle: 24×32px, centered in 64×64 canvas - Fill: D-033 relationship color at 90% opacity - Outline: 2px D-033 relationship color at 100% opacity - Label: NPC name or "Player", 11px Michroma, `#e8eaf0`, centered below rectangle (within canvas dead space) The label goes **below** the art rectangle, within the canvas — it's the name badge of the placeholder, not a floating HUD element. When sprites replace rectangles, labels are removed from the canvas and handled separately by the HUD. ### 3.3 Color Source Entity fill and outline color are **driven entirely by the client's derived relationship state** — not baked into the asset. The placeholder pipeline produces one generic rectangle shape; color is applied as a Godot shader parameter at runtime. This ensures the placeholder and the sprite system are architecturally identical. Implementation: `entity_color` shader uniform, set per entity per frame from `ObserverSnapshot.relationship_state`. ### 3.4 Player Character Placeholder Same spec as NPC placeholder, with these overrides: | Property | Detective | Smuggler | |----------|-----------|---------| | Fill color | `#e0e8ff` at 90% | `#e8e0d0` at 90% | | Outline | 2px `#e0e8ff` | 2px `#e8e0d0` | | Label | "YOU (DET)" | "YOU (SMU)" | --- ## 4. Animation Frame Requirements ### 4.1 v0.1 Animation: None All entities in v0.1 are **static placeholder sprites** — no animation. The animation tier system (D-047, visual grammar §6) defines what gets built for production art, not for placeholders. The placeholder pipeline must produce single-frame sprites. Do not build animation infrastructure for placeholder sprites. ### 4.2 Production Target (for pipeline planning) When placeholder sprites are replaced, the pipeline must support: | Tier | Entity type | Frame budget | Directions | |------|------------|-------------|------------| | Tier 1 (Active NPC) | Named + generic | 8 frames walk, 2–3 idle | 2 drawn (N/S), 2 mirrored (E/W) | | Tier 2 (Background NPC) | Generic only | 1 frame (static) | 1 direction, no mirroring needed | | Player | Both characters | Same as Tier 1 NPC | 2 drawn + 2 mirrored | Frame format for production sprites: PNG strip (horizontal), 64×64px per frame, filename convention: `entity_{name}_{direction}_{action}.png` (e.g., `entity_kael_south_walk.png`). --- ## 5. Color Palette Constraints ### 5.1 What the Placeholder Pipeline Produces The pipeline does not bake colors into assets. It produces **shape templates** that accept color as a runtime parameter (shader uniform or Godot modulate). This matches the production principle from D-043: "Sprites are shape templates that the lighting system completes." ### 5.2 Color Sources | Asset type | Color source | |-----------|-------------| | Entity fill + outline | `entity_color` uniform from `RelationshipState` (per entity, per frame) | | Object fill | Fixed per object type (see §2.2 table) | | Floor tiles | Fixed per zone (see visual grammar §1) | | Insert overlay | `#c8d0e0` chrome + D-033 relationship colors for entity markers | | Fog shader | Driven by LOS mask, not a color constant | ### 5.3 What Not to Do - Do not hardcode entity colors in art assets - Do not add zone-specific color variants of the same object shape — zone lighting handles the emotional temperature - Do not add object colors that compete with entity saturation (see visual grammar §3.6) --- ## 6. File Format and Asset Organization ### 6.1 Format | Context | Format | Notes | |---------|--------|-------| | All placeholder sprites | PNG | Alpha channel required for entity canvas dead space | | Production sprites (future) | PNG | Same. DDS conversion deferred to Phase 4 | | Shader assets | `.gdshader` in `client/shaders/` | Not part of placeholder art pipeline | ### 6.2 Asset Directory Structure ``` client/assets/ art/ placeholder/ tiles/ floor_logistics.png # 64×64px, solid #1a1e24 floor_bar.png # 64×64px, solid #1e1912 floor_corridor.png # 64×64px, solid #181818 wall_face.png # 64×64px, solid (zone-parameterized at runtime) wall_top.png # 64×64px, solid (zone wall top color, rendered at ~70% opacity on z-layer 4) door_closed.png # 64×64px door_open.png # 64×64px (threshold outline baked in) objects/ obj_generic.png # 64×64px grey rectangle (color via modulate) obj_terminal.png # 64×64px tinted, "TERMINAL" label obj_crate.png # 64×64px tinted, "CARGO" label entities/ entity_generic.png # 64×64px, 24×32 art area (color via shader) entity_player.png # 64×64px, same — player uses same shape production/ # Empty in v0.1, populated in Phase 2–4 ``` ### 6.3 Naming Convention `{category}_{identifier}.png` - Category: `floor_`, `wall_`, `obj_`, `entity_`, `door_` - Identifier: zone or type name, lowercase, underscores - No version suffixes in filename — versions are tracked by git ### 6.4 Source Dimensions Placeholder art is authored at **64×64px final size** — no resolution chain. Production art will use the 1024px → 256px → 64px resolution chain (D-043) when AI-generated assets enter the pipeline. The placeholder pipeline does not need to support this chain. --- ## 7. Lighting Constraints for Placeholder Art Sprites must be **authored as flat, neutral-lit shapes** so Godot's Light2D pipeline completes the mood. Do not bake: - Shadows (directional or point-source) - Lighting gradients (bright on one side, dark on other) - Ambient occlusion - Any lighting that implies a specific light source direction The PointLight2D pipeline (D-046) does all of this at runtime. Baked lighting in sprites will fight the runtime lighting and produce incoherent results as the player moves. **Test:** Drop a placeholder tile into a dark Godot scene with a single PointLight2D. The tile should look correct — lit on the side facing the light, dark on the far side. If it looks wrong, the sprite has baked lighting. --- ## 8. Phases Reference From the briefing — for pipeline planning: | Phase | Focus | Target | |-------|-------|--------| | **Phase 1 (current)** | Structural | Tile floor plans, entity rectangles, fog rendering. Blocks gameplay testing. | | **Phase 2** | Information | Insert overlay, monologue display, dialogue panel, sound indicators. Blocks content testing. | | **Phase 3** | Atmosphere | Zone palettes, lighting, span gate glow, character insert variants. Blocks experience testing. | | **Phase 4** | Polish | Sprite replacements, animations, particles. Pre-release. | **v0.1 target: Phases 1–3.** Zero image files — everything procedural. This spec covers Phase 1 asset requirements. Phases 2 and 3 derive from the visual grammar and will be addressed in subsequent tickets.