docs(visual): Sprint 12 — visual grammar and placeholder art spec
Delivers #303 (v0.1 Visual Grammar Document) and #252 (Placeholder Art Spec). #303 — visual-grammar-v01.md - 7 sections: zone color palettes (hex values, Zone 1/2/3), entity sizing/proportions (24x32px art area in 64x64px canvas, dual-scale grid per D-066), entity color system (D-033 relationship colors, transition behavior, saturation hierarchy), z-level rendering stack (8 layers, y-sort rules, wall rendering, overhead occlusion), typography baseline (Michroma at 4 role sizes, dialogue layout per D-061), animation tier baseline (D-047 Tier 1/Tier 2 with frame budgets), neural insert overlay (D-048 geometric/bloom spec, detective vs smuggler variants, fog interaction, insert-off behavior per D-056/D-057 OQ-07). - Closes #304 (entity color system spec — covered in §3). - Unblocks #311, #312, #313, #314, #315, #316, #317, #318, #334. #252 — placeholder-art-spec-v01.md - Tile dimensions: 64x64px visual tile, 32x32px sim tile, 1080p base resolution. - Structural tile colors per zone, object tile spec (tinted rectangles + labels). - Entity sprite spec: 24x32px art in 64x64px canvas, color-via-shader (no baked colors). - Animation scope: static placeholder in v0.1, production frame budgets documented. - File format (PNG with alpha), asset directory structure, naming convention. - Lighting constraints: no baked lighting, Light2D pipeline does all atmosphere. - Unblocks #133 (placeholder art pipeline). Cross-references: D-033, D-043, D-044, D-045, D-046, D-047, D-048, D-049, D-052, D-056, D-057, D-059, D-061, D-066. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
# 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) |
|
||||
| Door (closed) | 64×64 px | Same as wall face, 4px lighter | 1px `#333340` |
|
||||
| Door (open) | 64×64 px | Same as floor | 1px `#333340` at threshold edge |
|
||||
|
||||
**Transition strips** (zone boundary tiles): blend between zone floor colors over 1 tile width. Simple 50/50 split or gradient between the two zone floor colors.
|
||||
|
||||
### 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)
|
||||
door_closed.png # 64×64px
|
||||
door_open.png # 64×64px
|
||||
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.
|
||||
@@ -0,0 +1,386 @@
|
||||
# The Settled Reach — v0.1 Visual Grammar
|
||||
|
||||
**Version:** v0.1 (Sprint 12)
|
||||
**Author:** Araminta (Visual Designer)
|
||||
**Date:** 2026-02-19
|
||||
**Status:** Active — unblocks #304, #311, #312, #313, #314, #315, #316, #317, #318, #334
|
||||
|
||||
This document is the source of truth for all visual decisions in v0.1. Every subsequent visual deliverable references this document. If a decision here conflicts with a local assumption, this document wins. Open a ticket to amend it if the assumption is right.
|
||||
|
||||
**Core principle (D-043):** "Sprites are shape templates that the lighting system completes." No baked shadows, no baked lighting, no baked mood. The world is lit by Godot's Light2D pipeline; sprites carry shape and saturation, not atmosphere.
|
||||
|
||||
---
|
||||
|
||||
## 1. Color Palette — Zone Palettes and Global Constants
|
||||
|
||||
### 1.1 What the Environment Communicates
|
||||
|
||||
Per D-045 (environmental neutrality), the world layer **never shifts** in response to narrative state, conspiracy activation, or investigation progress. Zone palettes are fixed. The only information signals that can change are entity colors (§3), insert overlay density (§7), and monologue urgency. A player walking into the bar after discovering the conspiracy finds it **still warm and amber**. That indifference is intentional.
|
||||
|
||||
What communicates narrative state: **entities** (D-033 colors). What communicates mood: **lighting** (D-046 three-reference model). The environment communicates location, not drama.
|
||||
|
||||
### 1.2 Zone 1 — Logistics Hub (The Terminal)
|
||||
|
||||
Character: cool grey-navy institutional. Era 1 and Era 2 construction. CanvasModulate is the global ambient between light pools; all visible floor and wall color is revealed by PointLight2D fixtures at cool white temperature.
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Floor tile | `#1a1e24` | Dark cool grey-navy, Era 1 composite panels |
|
||||
| Wall face | `#2a3040` | Medium navy-grey, visible under tilt angle |
|
||||
| Wall top | `#222838` | Slightly darker than face; top surface of wall |
|
||||
| Ambient (CanvasModulate) | `#0e1218` | The darkness *between* light pools. Very dark cool blue-grey. |
|
||||
| Fixture light color | `#c8d8f0` | Cool institutional white-blue |
|
||||
| Fixture radius | 8–10 visual tiles | Wide, efficient workplace coverage |
|
||||
| Outline (global) | `#333340` | Dark blue-grey. Applied at 4–8px at 256px working resolution. |
|
||||
|
||||
Era 2 modifications (retrofits, junction boxes, modified partitions) share the same floor tile but use `#6d7178` for surface-mounted elements — slightly warmer than Era 1's `#7a7f85`, reflecting different production run.
|
||||
|
||||
### 1.3 Zone 2 — Bar (The Last Shift)
|
||||
|
||||
Character: warm dark, amber-lit, Era 3 construction. Irregular by design (D-043, "functional warmth"). The warmth is Lera's accumulated decisions, not zone theming — placement and density carry the feeling.
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Floor tile | `#1e1912` | Dark warm brown-grey, worn composite panels |
|
||||
| Wall face | `#2c2018` | Medium warm brown, Era 3 variation |
|
||||
| Wall top | `#221810` | Darker warm brown |
|
||||
| Ambient (CanvasModulate) | `#100c08` | Warm near-black. The bar is darker between pools — intimacy, not gloom. |
|
||||
| Fixture light color | `#f0b840` | Warm amber — social, inhabited (D-046 Blade Runner reference) |
|
||||
| Fixture radius | 5–6 visual tiles | Pooled, intimate. Light doesn't reach every corner. |
|
||||
| Outline (global) | `#333340` | Same outline as all zones — consistency is non-negotiable |
|
||||
|
||||
### 1.4 Zone 3 — Transition Corridors
|
||||
|
||||
Character: neutral dark, dim irregular lighting. Original Era 1 construction, maintained not renovated. Emptier because no one settled it (D-051 — "settling is placement").
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Floor tile | `#181818` | Neutral dark grey, industrial grating |
|
||||
| Wall face | `#242424` | Medium neutral dark |
|
||||
| Wall top | `#1a1a1a` | Marginally darker |
|
||||
| Ambient (CanvasModulate) | `#0c0c0c` | Near-neutral black. The coldest ambient. |
|
||||
| Fixture light color | `#d0d8e0` | Cold dim white. Maintenance grade. |
|
||||
| Fixture radius | 4–5 visual tiles | Sparse, uneven. Gaps between pools are wider. |
|
||||
| Outline (global) | `#333340` | Same as all zones |
|
||||
|
||||
### 1.5 Global Color Constants
|
||||
|
||||
These are not zone-specific. They apply everywhere.
|
||||
|
||||
| Constant | Hex | Usage |
|
||||
|----------|-----|-------|
|
||||
| Outline standard | `#333340` | All sprites, all zones, all layers |
|
||||
| Insert chrome | `#c8d0e0` | Default insert HUD color (cursor, grid lines, non-relationship data) |
|
||||
| Unexplored wireframe | `#333340` | Same as outline — geometric map app aesthetic |
|
||||
| Unexplored (no map) | `#12141a` | Solid near-black. Information zero. |
|
||||
|
||||
### 1.6 What Doesn't Get a Color
|
||||
|
||||
Danger, safety, tension, conspiracy — none of these get palette representation in the environment. They're carried by entities (§3) and insert density (§7). If you find yourself wanting to tint a tile orange because something bad happened there, that's the environment doing work it's not supposed to do.
|
||||
|
||||
---
|
||||
|
||||
## 2. Entity Sizing and Proportions
|
||||
|
||||
### 2.1 Grid Context
|
||||
|
||||
The dual-scale grid (D-066) separates simulation resolution from visual presentation:
|
||||
|
||||
- **Simulation tile:** 0.5m. All server-side logic (movement, LOS, pathfinding, occupancy) operates here.
|
||||
- **Visual tile:** 1m = 2×2 sim tiles. All client-side art is authored at this scale. **1 visual tile = 64×64 pixels at runtime.**
|
||||
- **Retina factor:** 2×. The simulation knows nothing about visual tiles — that's a client rendering convention.
|
||||
|
||||
### 2.2 Entity Sprite Dimensions
|
||||
|
||||
| Property | Value | Notes |
|
||||
|----------|-------|-------|
|
||||
| Sprite footprint | 2×2 sim tiles | Entities visually span one full visual tile (64×64px) |
|
||||
| Sprite art area | 24×32 px | Active art within the 64px canvas. Clear figure-ground against tile. |
|
||||
| Occupancy | 1×1 sim tile | Character occupies half a visual tile for sub-tile positioning precision |
|
||||
| Player sprite | 24×32 px art, 64×64 canvas | Same as NPC — no special sizing |
|
||||
| Named NPC | 24×32 px art, 64×64 canvas + 1 silhouette feature | Kael: vest ridge. Lera: apron shape. Sera: uniform collar. |
|
||||
| Generic NPC | 24×32 px art, 64×64 canvas, 3–4 template silhouettes | Rotated/mirrored from template set |
|
||||
|
||||
**Why 24×32 and not 32×32 or 64×64:** Entities must read clearly against the background without visually consuming the tile. Too large = visual clutter when multiple entities share an area. Too small = unreadable at a glance. 24×32 is the figure-ground minimum that keeps silhouette readable.
|
||||
|
||||
**Tilt implication (D-019 amendment):** The Rimworld shallow tilt (~15–20° from vertical) means sprites are authored with south-facing front faces. Draw 2 sprite directions: front-facing (south) and back-facing (north). Left/right are mirrors of these. The Godot camera is purely orthographic; the tilt is a drawn convention in the art.
|
||||
|
||||
### 2.3 Static Object Sizing
|
||||
|
||||
| Object type | Minimum footprint | Outline |
|
||||
|-------------|------------------|---------|
|
||||
| Small items (mug, comm, datapad) | 1×1 visual tile | 1px `#333340` |
|
||||
| Furniture (chair, terminal, crate) | 1×1 to 2×2 visual tiles | 1px `#333340` |
|
||||
| Large furniture (bar counter, desk array) | 2×1 to 3×1 visual tiles | 1px `#333340` |
|
||||
| Structural (walls, doors) | 2×2 sim tile minimum (= 1×1 visual tile) | Minimal to none |
|
||||
|
||||
**Hard rule (D-066):** All walls, furniture, crates, and doors occupy a minimum of 2×2 sim tiles. This ensures visual truth and sim truth agree on cover and LOS occlusion. No structural element is narrower than one visual tile.
|
||||
|
||||
### 2.4 Player Indicator
|
||||
|
||||
Both player characters use their D-033 base color as primary identification (see §3). There is no separate player indicator sprite in v0.1 — the player character is just an entity with distinct D-033 coloring and, eventually, a distinctive silhouette.
|
||||
|
||||
| Character | Entity sprite color | Notes |
|
||||
|-----------|-------------------|-------|
|
||||
| Detective | `#e0e8ff` (cool, faint blue-white) | Institutional, analytical register |
|
||||
| Smuggler | `#e8e0d0` (warm, faint amber-cream) | Social, camouflage register |
|
||||
|
||||
These are deliberately desaturated. The player should read clearly but not dominate the palette.
|
||||
|
||||
---
|
||||
|
||||
## 3. Entity Color System
|
||||
|
||||
*This section covers #304 content. Ticket #304 is closed by this document.*
|
||||
|
||||
### 3.1 Core Principle
|
||||
|
||||
Entity color encodes the **player character's subjective relationship** to an NPC — not an objective property of the NPC. The same NPC can appear as different colors to the detective and the smuggler. Color is a client-side derivation from `RelationshipState` component + knowledge state (D-033). The server never sends "this NPC is red" — it sends the information that the client derives color from.
|
||||
|
||||
This is asymmetric information rendered visually. It's the most important system in the game to get right.
|
||||
|
||||
### 3.2 Relationship Color Palette
|
||||
|
||||
| Relationship state | Color | Hex | Visual quality |
|
||||
|-------------------|-------|-----|----------------|
|
||||
| Unknown / Neutral | Cool teal | `#4a9ebb` | Default. Unassessed. Player knows they exist. |
|
||||
| Known / Friendly | Soft green | `#6bc9a6` | Trusted. Known person. Could still be THE FRIEND. |
|
||||
| Person of Interest | Warm amber | `#e8c547` | Something flagged this person. Monologue or case file. |
|
||||
| Hostile / Dangerous | Muted red | `#d45d5d` | Player character perceives *subjective* danger. Not omniscient. |
|
||||
| Static objects | Muted grey | `#8b8ba0` | Furniture, equipment, environmental. Non-person. |
|
||||
|
||||
**Red means danger to your character**, not danger in the abstract. A detective might see amber (person of interest) where the smuggler sees green (trusted colleague) for the exact same NPC. Both are correct — from their position.
|
||||
|
||||
### 3.3 Player Characters
|
||||
|
||||
| Character | Color | Hex |
|
||||
|-----------|-------|-----|
|
||||
| Detective | Cool blue-white | `#e0e8ff` |
|
||||
| Smuggler | Warm cream | `#e8e0d0` |
|
||||
|
||||
Player colors are deliberately near-neutral. They should read as "self" without the loaded meaning of the NPC colors.
|
||||
|
||||
### 3.4 Transition Behavior
|
||||
|
||||
Color shifts are **0.5-second smooth fades**. Never instant. The visual transition IS the information delivery — the player reads the relationship changing, not a sudden color swap.
|
||||
|
||||
**THE FRIEND's first shift** (green → amber) must be the **first relationship color change** in the session. Stage the opening 20–25 minutes so no other relationship state change precedes it. This is wow moment #3 (D-039); the visual punch depends on the player having already internalized what green means.
|
||||
|
||||
### 3.5 Interaction with Insert Overlay
|
||||
|
||||
In the insert overlay (z-layer 6, §7), entity D-033 colors gain soft halos (2–3px gaussian blur at ~40% blend). In the natural vision layer (z-layer 3), they're rendered with 2px outline in the relationship color — hard edge, no bloom. The bloom is the insert's interpretation; the hard edge is the player's naked eye.
|
||||
|
||||
### 3.6 Saturation Hierarchy
|
||||
|
||||
Entity D-033 colors are the most saturated elements in any scene. Object-layer favorite colors (D-052) must stay below D-033 entity saturation to preserve visual hierarchy.
|
||||
|
||||
| Hierarchy tier | Saturation range | Examples |
|
||||
|----------------|-----------------|---------|
|
||||
| Entity (D-033) | High: 40–60% | `#4a9ebb`, `#6bc9a6`, `#e8c547`, `#d45d5d` |
|
||||
| Objects (D-052 favorites) | Moderate: 15–30% | Dusty blue, warm terracotta, faded olive (muted register) |
|
||||
| Structure (zone palette) | Low: 5–15% | Zone floors, wall faces, tiles |
|
||||
|
||||
Never introduce an object color that competes with entity color saturation.
|
||||
|
||||
---
|
||||
|
||||
## 4. Z-Level Rendering Stack
|
||||
|
||||
### 4.1 The 8-Layer Stack
|
||||
|
||||
Per D-049. Layers are Godot CanvasLayer z-indices. Higher index = renders on top.
|
||||
|
||||
| Z-index | Name | Contents | Notes |
|
||||
|---------|------|----------|-------|
|
||||
| **0** | Floor tiles | Zone floor panels, grating, transition strips | Muted zone palette. Lowest saturation. No outlines on floors. |
|
||||
| **1** | Floor objects | Cosmetic floor detail (dirt, markings, decals) | Walked over. No gameplay interaction. |
|
||||
| **2** | Furniture / placed objects | Desks, chairs, crates, bar counter, terminals | Y-sorted with z-layer 3 for overlap resolution |
|
||||
| **3** | Entity sprites | All characters (player + NPCs) | Y-sorted with z-layer 2. D-033 colored. 2px outline. |
|
||||
| **4** | Overhead / wall tops | Pipes, ducts, signage, lighting fixtures, wall tops | Semi-transparent partial occlusion (~70% opacity). Creates information gaps within known spaces. |
|
||||
| **5** | Fog of perception | Vision cone mask + fog shader + sound ping sprites | Affects layers 0–4. Does NOT affect layers 6–7. |
|
||||
| **6** | Insert overlay | Lattice HUD elements, relationship markers, cursor, interaction labels | Bloom-rendered. NOT masked by fog — computational, not perceptual. |
|
||||
| **7** | Monologue / UI | Internal monologue text, dialogue box, world menu, HUD chrome | Always visible. Top of stack. |
|
||||
|
||||
### 4.2 Y-Sorting Rule
|
||||
|
||||
Layers 2 and 3 are y-sorted together. An entity moving behind a desk disappears correctly. An entity standing in front of a desk renders in front. The y-sort key is the entity's or object's bottom-most sim tile position.
|
||||
|
||||
**Never override y-sort manually** for specific entity/object pairs. The rule applies universally.
|
||||
|
||||
### 4.3 Wall Rendering
|
||||
|
||||
- **Structural walls (load-bearing, room dividers):** Option B — visible top face + south-facing wall face (visible under tilt angle). Top face on z-layer 4, face on z-layer 2 boundary.
|
||||
- **Interior partitions (half-walls, furniture dividers):** Option A — boundary lines only. Minimal visual weight.
|
||||
|
||||
### 4.4 Overhead Occlusion
|
||||
|
||||
Layer 4 objects render at ~70% opacity when the player is beneath them. This creates **local information gaps within otherwise known spaces** (Gore's observation, D-049). An NPC behind a shelving unit in a fully explored room still partially disappears — the exploration context (fog state) doesn't grant omniscience about what's behind objects.
|
||||
|
||||
This is a thematic system as much as a rendering one. Don't eliminate it for "clarity."
|
||||
|
||||
---
|
||||
|
||||
## 5. Typography Baseline
|
||||
|
||||
### 5.1 Typeface
|
||||
|
||||
**Michroma** (Google Fonts, Regular 400, free for commercial use) is the sole typeface for all player-facing text in v0.1.
|
||||
|
||||
Michroma is geometric sans-serif — technical, clean, forward-facing without being aggressive. It fits the insert aesthetic: the character is reading their own neural lattice output. All text, including dialogue and environmental labels, renders as if through this lens. There is no "game UI font" vs "world font" — Michroma is both.
|
||||
|
||||
### 5.2 Text Size and Role Specifications
|
||||
|
||||
All sizes are in pixels at 1080p (1920×1080) base resolution. Godot 4 handles DPI scaling.
|
||||
|
||||
| Text role | Size | Opacity | Color | Z-layer | Notes |
|
||||
|-----------|------|---------|-------|---------|-------|
|
||||
| Dialogue — NPC speech | 16px | 100% | `#e8eaf0` | 7 | Max width ~70% screen width. Left-aligned. |
|
||||
| Dialogue — player response | 14px | 90% | `#c0c8d8` | 7 | Below NPC speech. Up to 3 options visible. |
|
||||
| Monologue (standard) | 13px | 85% | `#d0d4e0` | 7 | Floats above dialogue box. Inner voice — slightly dimmer than dialogue. |
|
||||
| Monologue (urgent) | 13px | 100% | `#e0e8f8` | 7 | Same size, full opacity, slight bloom pulse. Urgent chime accompanies. |
|
||||
| Environmental text | 11px | 70% | `#8899aa` | 2–4 | Labels on terminals, signs, lockers. Part of the world. Muted. |
|
||||
| HUD / insert chrome | 12px | 80% passive, 100% active | `#c8d0e0` | 6 | Time display, insert labels, menu chrome |
|
||||
| Interaction verbs | 13px | 95% | D-033 color of target | 6 | Rendered on insert z-layer. Disappears when insert off. |
|
||||
| Confrontation weight | 15px | 100% | `#e0e8f0` | 7 | Same box as dialogue but heavier visual weight — wider, higher contrast frame |
|
||||
|
||||
### 5.3 Dialogue Box Layout (D-061)
|
||||
|
||||
- **Position:** Bottom of screen, full screen width (max-width)
|
||||
- **Max height:** 20% of screen height
|
||||
- **Layout:** NPC speech on top line, response options stacked below, left-aligned
|
||||
- **Max visible response options:** 3
|
||||
- **Locked options:** Invisible — player never sees what they can't access
|
||||
- **No portraits:** The NPC is on screen. A portrait is redundant.
|
||||
|
||||
Monologue on z-layer 7 floats above the dialogue box, **not inside it**. This spatial separation allows monologue to contradict dialogue visually — the character thinks one thing (above, inner) while the NPC speaks another (below, outer).
|
||||
|
||||
### 5.4 Text That Does NOT Get Michroma
|
||||
|
||||
Nothing. All text goes through Michroma. Handwritten signs, terminal readouts, personal notes — all render in Michroma at appropriate size and opacity. The fiction is that everything is mediated through the player character's neural insert perception layer.
|
||||
|
||||
---
|
||||
|
||||
## 6. Animation Tier Baseline
|
||||
|
||||
### 6.1 Two-Tier System (D-047)
|
||||
|
||||
The animation system has two tiers, and the boundary between them is **invisible to the player**. This invisibility is the mechanic: routine is readable, so deviation is noticeable, so the player can't be sure what they're seeing.
|
||||
|
||||
**Tier 1 — Clear (Active NPCs):**
|
||||
Publicly motivated behavior. Instantly readable from a glance. Player can determine intent.
|
||||
|
||||
| Animation | Frames | Notes |
|
||||
|-----------|--------|-------|
|
||||
| Idle | 2–3 frames | Subtle breathing cycle. Not distracting. |
|
||||
| Walk | 8 frames (2 directions × 4 frames, mirrored for L/R) | 4-directional coverage. North/south are distinct draws; east/west are mirrors. |
|
||||
| Working at terminal | 2–3 states | Key-tap, pause, review. Readable as "doing their job." |
|
||||
| Handling cargo | 2–3 states | Lift, carry, set down. |
|
||||
| Eating / drinking | 2–3 states | Raise, consume, lower. Readable as "on break." |
|
||||
| Talking | 2–3 states | Slight lean, gesture. Distinguishable from "standing near." |
|
||||
| Sleeping | 1 state | Static prone. Unambiguous. |
|
||||
|
||||
**Tier 2 — Ambiguous (Background NPCs + deliberate Tier 1 ambiguity):**
|
||||
Privately motivated behavior. Observable but not interpretable. The player sees the action but cannot determine the intention.
|
||||
|
||||
| Behavior | Appearance | Ambiguity |
|
||||
|----------|-----------|-----------|
|
||||
| Pausing | Standing idle | Break? Waiting? Watching? |
|
||||
| Looking around | Head turn (1 frame) | Nervous? Checking for someone? Habit? |
|
||||
| Lingering near location | Idle near an object | Interested? Positioned? Coincidence? |
|
||||
| Changing direction | Mid-path turn | Remembered something? Avoiding someone? |
|
||||
| Proximity without interaction | Near entity, no Tier 1 state | Protecting? Monitoring? Coincidence? |
|
||||
|
||||
**The line between tiers is the investigation mechanic.** Tier 1 is the baseline everyone reads. Tier 2 is what creates the signal-from-noise problem that makes investigation interesting.
|
||||
|
||||
### 6.2 v0.1 Animation Scope
|
||||
|
||||
In v0.1, all entities start as colored rectangles with labels (D-014: "functional boxes with labels"). The animation system defines what gets built when we graduate past rectangles.
|
||||
|
||||
- Phase 1 (current): Colored rectangle + name label. No animation.
|
||||
- Phase 2 (sprite replacement): Tier 1 walk cycle + idle for Active NPCs. Static sprite for Background NPCs.
|
||||
- Phase 4 (polish): Full Tier 1 set, Tier 2 behavioral states, player character expressions.
|
||||
|
||||
**Background NPCs (Tier 2 only) never get animation in v0.1.** They are static sprites. The cost of animating 500–2,000 Background-tier NPCs is not justified when their visual presence is already deliberate and readable.
|
||||
|
||||
---
|
||||
|
||||
## 7. Neural Insert Overlay
|
||||
|
||||
### 7.1 Visual Language
|
||||
|
||||
The insert overlay (z-layer 6) is a **geometric data layer** rendered with an **organic delivery**:
|
||||
|
||||
- Data structure: precise positioning, clean geometric lines, structured information layout
|
||||
- Neural delivery: ~2–3px gaussian blur at ~40% blend on the insert CanvasLayer
|
||||
- Result: "amber feels like a vague sense of concern, not a data flag" (Araminta, D-048)
|
||||
|
||||
The insert is not an HUD bolted onto a game. It IS the character's neural lattice. If switching it off would feel like going deaf rather than closing a window, it's working. After 10 minutes, the player should forget it's there.
|
||||
|
||||
### 7.2 Character Variants
|
||||
|
||||
Both characters use the same underlying system. The `lattice_profile` parameter on the `ObserverSnapshot` determines which variant renders.
|
||||
|
||||
| Property | Detective (`lattice_augmented`) | Smuggler (`lattice_baseline`) |
|
||||
|----------|--------------------------------|------------------------------|
|
||||
| Line weight | 1–2px | 1px |
|
||||
| Annotation density | Dense — more markers, more connection lines | Sparse — essential markers only |
|
||||
| Passive opacity | 80% | 60% |
|
||||
| Active opacity | 100% | 85% |
|
||||
| Bloom intensity | 40% blend at 2–3px gaussian | 40% blend at 2–3px gaussian (same — different density, same feel) |
|
||||
| Color | D-033 relationship colors + `#c8d0e0` chrome | Same |
|
||||
|
||||
The detective has augmented lattice hardware — they see more, more precisely. The smuggler has baseline — they see what they need, no more. The asymmetry isn't which colors appear, it's how much annotation the overlay generates from the same underlying data.
|
||||
|
||||
### 7.3 Fog Interaction
|
||||
|
||||
**The insert overlay is NOT affected by the fog shader.** Fog lives on z-layer 5 and masks z-layers 0–4. The insert (z-layer 6) and UI (z-layer 7) are not masked.
|
||||
|
||||
Insert markers can appear in fogged areas if the lattice has that data. A known-friendly NPC behind a wall can still appear as a green halo in the fog — the character's lattice tracks the last known position. This is insert data, not visual data. The character knows, even if they can't see.
|
||||
|
||||
### 7.4 Soft Degradation
|
||||
|
||||
At high perception load (multiple overlapping modes), the insert shows **diegetic scan-line interference** — subtle horizontal distortion at ~5% intensity. No hard cap on simultaneous perception modes. The degradation is visual warning, not mechanical punishment. Player reads it as "the insert is working hard." (D-059, D-048)
|
||||
|
||||
### 7.5 Insert-Off Behavior (D-056/D-057 — OQ-07 Resolution)
|
||||
|
||||
When `insert_active == false`:
|
||||
- Cursor shape still changes (entity hover → bracket shape, object hover → X-shape) — the character's body responds subconsciously to proximity
|
||||
- Interaction labels (z-layer 6) are suppressed — the insert doesn't process targets without activation
|
||||
- `should_show_interactions()` returns false
|
||||
- Insert markers in fog disappear — the lattice isn't running position tracking
|
||||
- **Bloom disappears** — no insert, no neural rendering pass
|
||||
|
||||
The character still moves and physically orients toward entities. The insert stops annotating.
|
||||
|
||||
---
|
||||
|
||||
## Appendix A — Decision Cross-References
|
||||
|
||||
| Decision | Relevance |
|
||||
|----------|-----------|
|
||||
| D-033 | Entity color = relationship to player. Defines all NPC and player entity colors. |
|
||||
| D-043 | Art direction — "functional warmth." Style, asset pipeline, production principle. |
|
||||
| D-044 | Visual hierarchy (entity > object > structure). Outline weights, saturation rules. |
|
||||
| D-045 | Environmental neutrality — strict zero shift. Zone palettes never change. |
|
||||
| D-046 | Lighting — three-reference model (Darkwood, BR2049, Hopper). Zone light temperatures. |
|
||||
| D-047 | Two-tier animation system. Tier 1 clear / Tier 2 ambiguous. |
|
||||
| D-048 | Neural insert overlay visual design. Bloom spec, character variants. |
|
||||
| D-049 | Z-level rendering stack — 8 layers. |
|
||||
| D-052 | Character favorite colors — object-layer identification. Saturation constraint. |
|
||||
| D-056 | Cursor states — insert-styled geometric. Four states, 150ms transitions. |
|
||||
| D-057 | Entity interaction — vertical list, insert-styled. |
|
||||
| D-059 | Fog shader — 5 layers, knowledge-graph-driven. Fog entities spec. |
|
||||
| D-061 | Dialogue box — bottom screen, max 20% height, no portraits. |
|
||||
| D-066 | Dual-scale grid — 0.5m simulation, 1m visual, 64x64px visual tiles. |
|
||||
|
||||
## Appendix B — What This Document Does Not Cover
|
||||
|
||||
The following are out of scope for v0.1 visual grammar and will be specified in separate documents when unblocked:
|
||||
|
||||
- **Insert/HUD wireframe** — dual character variants in detail (#314, blocked by this doc)
|
||||
- **Monologue display system** — typography animation, stacking, voice differentiation (#315)
|
||||
- **Text display hierarchy** — 4 content pipelines (#316)
|
||||
- **Sound indicator visual design** — fog-edge ping pulse (#317)
|
||||
- **THE FRIEND visual treatment** — after Paula's NPC profiles (#318)
|
||||
- **Environmental text standards** — sign conventions, terminal text (#334)
|
||||
- **Spatial layouts** — tile-level floor plans (#311, #312, #313, all blocked by this doc)
|
||||
Reference in New Issue
Block a user