Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
119 lines
7.5 KiB
Markdown
119 lines
7.5 KiB
Markdown
---
|
||
title: "Sprint 28 — Client Briefing"
|
||
description: "Sprite layer compositor and character creation screen implementation"
|
||
type: sprint
|
||
status: planning
|
||
sprint: 28
|
||
team: "client"
|
||
---
|
||
|
||
# Sprint 28: Character Visuals — Client Tasks
|
||
|
||
**Goal:** Move beyond placeholder art to final product candidate character visuals, from design specs through asset production and compositor implementation.
|
||
|
||
**Branch:** `client`
|
||
**Agents:** Stig (dev), Tyre (arch), Hoshe (QA)
|
||
|
||
## New Tickets
|
||
|
||
| # | Title | Blocked by |
|
||
|---|-------|------------|
|
||
| #693 | Sprite layer compositor | #684 (workshop), #686 (body type sprites) |
|
||
| #694 | Character creation screen | #685 (wireframe), #693 (compositor) |
|
||
|
||
Use `tooling/db/ticket show <id>` for full details.
|
||
|
||
## Key Decisions
|
||
|
||
- `decisions/architecture.md` — D-134 (full character customisation: hair, clothing, colors at tile scale), D-146 (character creation preview: tile-scale sprite with heavy zoom — the compositor IS the preview renderer, no separate portrait system), D-043 (art direction: "functional warmth"), D-044 (visual hierarchy)
|
||
- `decisions/content.md` — D-147 (aesthetic taste as character personality trait — compositor reads layer choices, does not write to apartment generator)
|
||
|
||
## Notes
|
||
|
||
### Existing code to understand first
|
||
|
||
Before starting either ticket, read:
|
||
|
||
- `client/scripts/rendering/entity_renderer.gd` — the current entity sprite system. It creates one `Sprite2D` per entity, loads textures from `client/assets/sprites/npc_generic_{direction}_64.png`, applies `self_modulate` for D-033 relationship tinting, and handles 4-direction rotation. The compositor replaces the single-sprite model for the player character with a multi-layer node stack.
|
||
- `client/scenes/character_select.tscn` + `client/ui/character_select.gd` — the existing character archetype selection panel (two-card overlay, keyboard + mouse). The new character creation screen (#694) lives in the same flow, after archetype selection.
|
||
- `client/scripts/constants.gd` — TILE_SIZE, entity footprint constants (ENTITY_WIDTH=24, ENTITY_HEIGHT=32), color constants.
|
||
- `client/scripts/autoloads/game_state.gd` — player entity ID and state. The compositor will need to know the player entity to apply the correct layer stack during gameplay.
|
||
|
||
### #693 — Sprite layer compositor
|
||
|
||
**Blocked by:** #684 (workshop spec) and #686 (body type sprites available as test input).
|
||
|
||
Wait for `docs/design/compositor-api-spec.md` (output of #684) before writing the compositor architecture. Do not design the layer API yourself — the workshop decides the layer ordering, color override struct, and Godot node architecture. This note describes what the compositor must accomplish, not how.
|
||
|
||
**What the compositor must do:**
|
||
- Accept a character definition (layer choices + color overrides) and render the composited character sprite in the correct layer order
|
||
- Support 8-direction rotation (or 4-direction if workshop spec reduces this) — swaps all layer textures simultaneously
|
||
- Apply color mesh recoloring per layer (color region ID → Color mapping) using the mesh regions defined in the visual spec
|
||
- Handle occlusion rules (e.g. helmet clothing hides hair layer)
|
||
- Expose a node or API that `EntityRenderer` can use for the player character in gameplay
|
||
- Expose the same node/API for use in the character creation screen preview pane (#694)
|
||
|
||
**Integration point with EntityRenderer:**
|
||
The current `EntityRenderer` creates a bare `Sprite2D` for each entity. For the player character, the compositor replaces this with a layered `Node2D` subtree. The cleanest integration: compositor exports a `Node2D` root that EntityRenderer parents under the entity position node, same as it would a `Sprite2D`. EntityRenderer detects `entity_id == GameState.player_entity_id` and uses the compositor node instead of a single sprite.
|
||
|
||
**Color mesh recoloring approach in Godot:**
|
||
Godot 4 does not have a built-in color mesh system. Options:
|
||
1. Per-layer `self_modulate` (works only for solid single-color regions — too limited)
|
||
2. Shader-based recoloring: pass a `from_color` and `to_color` uniform, replace pixels matching `from_color` within a threshold. This is the standard tile-game approach.
|
||
3. Multiple texture layers per sprite (premultiplied masks).
|
||
|
||
Wait for workshop spec to select the approach. If the workshop spec is silent on implementation, use option 2 (shader-based) — it is the most flexible and supports arbitrary palette swaps without new textures.
|
||
|
||
**File locations:**
|
||
- Compositor script: `client/scripts/rendering/character_compositor.gd`
|
||
- Compositor scene (if needed as a PackedScene): `client/scenes/character_compositor.tscn`
|
||
- Shader (if approach 2): `client/shaders/character_recolor.gdshader`
|
||
|
||
### #694 — Character creation screen
|
||
|
||
**Blocked by:** #685 (wireframe design) and #693 (compositor for the preview pane).
|
||
|
||
This is the full implementation of the wireframe produced by #685. Do not start until `docs/design/character-creation-screen-wireframe.md` exists and is approved.
|
||
|
||
**What the screen must deliver:**
|
||
- Layer selection controls for each character layer type (body, face, hair, clothing, accessories, scars, tattoos)
|
||
- Live preview pane showing the composited character at heavy zoom (tile-scale sprite, zoomed in — same sprite that appears in gameplay)
|
||
- Color picker or palette selector per colorable region
|
||
- Randomise button (randomises all layer choices and color selections)
|
||
- Confirm / Back navigation
|
||
- Full keyboard + mouse support (matching existing character_select.gd pattern — left/right/tab navigation, Enter to confirm, Esc to cancel)
|
||
|
||
**Integration into game flow:**
|
||
The existing flow: `main_menu.tscn` → `character_select.tscn` (archetype card). The new flow inserts character creation after archetype selection (or replaces the archetype select, depending on how #684 resolves the bookmark/archetype question). Wire the scene transition from the existing entry point.
|
||
|
||
**Preview pane — D-146:**
|
||
The preview is the gameplay sprite, zoomed. The compositor (#693) provides this. The preview pane is a `SubViewport` or a simple `Node2D` with the compositor node, scaled up. Heavy zoom means: render the 32×32 gameplay sprite at 4× or 6× scale so individual pixels are visible and character detail reads clearly. Rimworld uses approximately 4×–6× zoom on its character customisation screen.
|
||
|
||
**Data flow:**
|
||
- Character creation screen maintains a `CharacterDefinition` (layer choices + color overrides)
|
||
- On any change, pushes the updated definition to the compositor — compositor re-renders the preview in real time
|
||
- On confirmation, stores `CharacterDefinition` to `GameState` (or session state) for use by the game on load
|
||
- The `CharacterDefinition` structure is defined by the compositor API spec (from #684)
|
||
|
||
**File locations:**
|
||
- Scene: `client/scenes/character_creation.tscn`
|
||
- Script: `client/ui/character_creation.gd`
|
||
|
||
## Dependency Chain
|
||
|
||
```
|
||
#684 (workshop) ──┬──> #693 (compositor)
|
||
#686 (body sprites) ──┘ └──> #694 (creation screen)
|
||
↑
|
||
#685 (wireframe) ────────────────────┘
|
||
```
|
||
|
||
Both #693 and #685 must be complete before #694 can start. #693 and #685 can run in parallel.
|
||
|
||
## PR Workflow
|
||
|
||
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see `CLAUDE.md` "Gitea access" section):
|
||
```bash
|
||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): character sprite compositor and creation screen" --description "body" --base main --head client
|
||
```
|