Files
settled-reach/docs/design/sound-indicator-visual.md
T
jpmschweitzerandClaude Opus 4.6 934d4df4b0 docs(docs): add frontmatter to all design docs
Standardized YAML frontmatter on all 40 docs/design/ files with title,
description, type, status, ticket, decision_refs, and author fields.
Covers specs, wireframes, voice cards, spatial layouts, and system
designs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:22:17 +01:00

13 KiB
Raw Blame History

title, description, type, status, ticket, decision_refs, author, created, updated
title description type status ticket decision_refs author created updated
Sound Indicator Visual Design Fog-edge pulse specification for directional sound indicators with range differentiation and suppression rules design active #317
D-018
D-033
D-047
D-048
D-049
D-059
D-070
Araminta 2026-02-20 2026-02-20

Sound Indicator Visual Design — Fog-Edge Pulse Specification

Version: v0.1 (Sprint 14) Author: Araminta (Visual Designer) Date: 2026-02-20 Ticket: #317 Status: Active — constrains client sound_indicator_renderer.gd implementation Foundation: Visual Grammar v0.1, Decision D-018 (three-range sound model)


1. Purpose and Scope

Sound indicators are complementary to audio, not a replacement for it. They exist for players with audio off, in loud environments, or when audio is present but directionality is ambiguous. They should not be noticeable during routine exploration — only when something specific warrants attention.

The v0.1 implementation uses directional arrows at the viewport edge as the indicator shape (already implemented in sound_indicator_renderer.gd). This spec defines the full intended visual design including the pulse behavior described in the ticket, and notes where the current implementation differs from the spec.

D-018 scope: Sound indicators cover the medium-range tier (sounds outside LOS, within ~320 tiles). Close-range sounds (≤3 tiles, within LOS) are handled by positional 2D audio — no indicator needed. Within medium range, three sub-tiers (close-medium, standard, far-medium) differentiate visual intensity — see §7 for the full breakdown.


2. Colors

Per D-018 three-range sound model and D-033/D-048 color vocabulary:

Sound category Hex Usage
Neutral #c8d0e0 Footsteps, ambient movement, cargo handling, non-social activity
Voice #e8c547 NPC conversation, speech, social activity
Danger #d45d5d Alarms, alerts, gunshots, explosions, threats

These are the same as the insert chrome color (#c8d0e0), the Person of Interest amber (#e8c547), and the Hostile red (#d45d5d). The alignment is intentional — the sound indicator system is part of the insert overlay, and its color vocabulary maps directly to the entity relationship system. A voice indicator uses the same amber as a Person of Interest entity because voices are people, and people are potentially interesting.


3. Position — Fog Edge, Not Screen Edge

3.1 Principle

Sound indicators live at the boundary of the player's visible cone — where clear vision meets fog. Not at the physical screen border, not as a minimap overlay.

The current implementation projects indicators to the viewport boundary (approximately correct — viewport edge ≈ fog edge at the camera's field of view). This is sufficient for v0.1. The spec's intent is that indicators should feel like they're at the perceptual boundary, not tacked to the UI chrome.

EDGE_INSET = 20.0px in the current implementation provides the correct "just inside the boundary" feel.

3.2 Z-Layer

Sound indicators render on z-layer 6 (insert overlay), not z-layer 5 (fog). They are insert data — the character's lattice is processing the sound, not the character's naked ears. They are unaffected by the fog shader.

The current implementation (sound_indicator_renderer.gd) renders as a Node2D draw call. This should be confirmed as rendering on z-layer 6 in the scene tree.


4. Shape — Arrow vs Pulse Arc

4.1 Current Implementation

The current sound_indicator_renderer.gd renders filled arrowhead triangles:

  • Tip at the viewport boundary edge point
  • Arrow points toward the sound source
  • Size: 12px length, 7px half-width
  • Filled polygon, not an outline

This is a valid v0.1 placeholder. It communicates direction clearly.

4.2 Target Design — Pulse Arc Segment

The intended final design is a thin arc segment at the fog boundary rather than a solid arrow. The arc reads as "sound reaching the edge of perception" rather than "here is an arrow pointing at something."

Property Value Notes
Shape Arc segment (partial ring) Centered on source direction, 40° sweep
Arc radius 6px — visually thin Not a thick ring
Position Fog boundary Radiates outward from boundary inward by 3px
Animation Pulse outward and fade Single pulse per event, see §5

Arc sweep: 40° centered on the direction to the sound source. Narrow enough to clearly point, wide enough to be visible at a glance. A line would be too thin; a semicircle too vague.

For v0.1: Continue using the current arrow implementation. The arc design is the target for when sprite art replaces colored rectangles — the arc will feel more natural against full art than a solid arrowhead.


5. Animation — Pulse Behavior

5.1 Current Implementation

The current implementation renders a static indicator (no pulse animation) that lives for INDICATOR_LIFETIME = 3.5s and fades over the last FADE_DURATION = 0.6s. The fade is a linear alpha ramp from full opacity to 0.

This is functional but does not communicate the sound event as a moment — it reads as a persistent marker rather than an alert.

5.2 Target Pulse Specification

The intended animation is a single expanding pulse per sound event, not a persistent marker:

Phase Duration Behavior
Onset 0.00.2s Indicator appears at full opacity, max brightness
Expand 0.20.6s Indicator expands outward by 34px (for arrow: scale 1.0 → 1.3)
Hold 0.61.5s Full opacity, static size
Fade 1.52.5s Linear alpha 100% → 0%

Total duration: 2.5s (vs current 3.5s). The shorter duration prevents indicators from lingering as persistent clutter.

For v0.1: Implement the onset flash (full opacity on appear) and the fade. Skip the expand animation if performance is constrained — the expand is polish.

Easing: Onset is instant (no fade-in — sound events are sudden, their indicators should be too). Fade-out uses ease-in (slow start, accelerates to transparent). The sound indicator should feel like it vanishes rather than slowly becoming invisible.

5.3 Deduplication

Same-source deduplication is already implemented correctly: if an indicator exists at a tile position, new events reset its timer rather than stacking. This prevents a continuous conversation from spawning dozens of overlapping indicators.


6. Direction Encoding

6.1 Arrow Direction

The current implementation projects the indicator to the viewport boundary in the direction of the sound source from the player. The arrowhead tip points toward the sound source. This correctly encodes direction.

Rule: The indicator tip always points toward the source, not away from it. The player reads "the sound is in that direction."

6.2 Arc Direction (Target Design)

In the arc design, the arc is centered on the direction vector from player to sound source. The arc's midpoint lies on the line from player to source, at the fog boundary. The 40° sweep is centered on this midpoint. The arc opens toward the source (the open side of the arc faces the player, the midpoint faces the source).


7. Range Differentiation — Three Visual Levels

D-018 specifies three distance ranges. Sound indicators apply to medium range (outside LOS), but within medium there are visual levels based on proximity:

Distance Visual treatment Alpha Notes
Close-medium (35 tiles) Full indicator, 90% alpha 90% Clear, noticeable
Standard medium (512 tiles) Standard indicator, 70% alpha 70% Visible but not urgent
Far-medium (1220 tiles) Smaller indicator, 45% alpha 45% Subtle, ambient

For the arrow implementation: Scale the arrow by distance proxy — close-medium at scale(1.0), far-medium at scale(0.7). The size reduction plus alpha reduction creates a clear near-vs-far reading.

Alpha cap at 90%: Sound indicators should never be fully opaque. They are insert data, not a HUD alert. The 10% transparency gap maintains their insert-layer quality.


8. Suppression Rules — When Indicators Do NOT Appear

Sound indicators are suppressed in the following conditions:

Condition Rule
Sound source within player's LOS Suppressed. The player can see/hear the source directly.
Sound source at close range (≤3 tiles) Suppressed. Close range is handled by positional 2D audio.
Sound source outside 20-tile radius Suppressed. Long-range sounds are insert notification territory (future sprint).
insert_active == false Suppressed. Sound indicators are insert overlay elements (z-layer 6).
Danger-category sound, player already in dialogue Not suppressed. Danger indicators break through dialogue focus. (See note.)

Dialogue suppression exception for Danger: Per D-070 (confrontation as cognitive vulnerability), ambient sounds are muffled during confrontation/dialogue — but this is audio suppression, not visual suppression. If an alarm fires while the player is in dialogue, the danger indicator should still appear. The player may not hear the alarm (audio is dipped) but the insert catches it. This is the insert doing its job: processing data the character's conscious attention missed.

Voice indicator suppression logic: event_type containing "voice"/"speech"/"convers"/"talk" → Voice category. This is already implemented in color_for_type() in the current renderer. No change needed.


9. Current Implementation vs Spec — Delta Summary

Aspect Current (v0.1) Target (spec)
Shape Filled arrowhead Arc segment (40°, 6px radius)
Animation Static + linear fade (3.5s total) Pulse onset + fade (2.5s total)
Range differentiation None — all indicators same size Three levels: 3px scale + alpha
Z-layer Needs confirmation Z-layer 6 (insert overlay)
Direction Correct — arrow points toward source Same principle, different shape
Colors Correct — uses Constants palette Same
Deduplication Correct — resets timer on re-trigger Same
Insert-off suppression Not yet implemented Suppress when insert_active == false

v0.1 implementation priority:

  1. Confirm z-layer 6 placement (quick fix if wrong)
  2. Add insert-off suppression
  3. Add basic range alpha differentiation (single alpha pass by distance)
  4. Keep arrow shape — replace with arc when sprite art arrives

10. Visual Design Rationale

Why at the fog edge, not screen edge or minimap?

Screen-edge indicators have no spatial relationship to the game world — they're purely navigational UI. The fog boundary is where the character's perception ends. A sound at the fog edge is a sound at the limit of what the character can process. Placing the indicator there is diegetically honest: the character's insert is flagging something at the edge of their awareness, not beyond it.

Minimap overlays require a minimap. We don't have one in v0.1. And minimap is meta-game — the indicator at the fog edge is in-world.

Why single pulse, not persistent marker?

Sound is a moment, not a state. A sound event happens at a point in time and then is over. A persistent marker would imply "there is still a sound here," which isn't necessarily true. The single pulse says "something happened in that direction." The player acts on it or doesn't.

Why amber for voice, not a neutral sound color?

Because voices are the most important medium-range sound in the game. NPCs talking to each other is signal. Footsteps are noise. Making voice indicators amber — the same as Person of Interest entity color — trains the player to associate amber with "social activity worth paying attention to." The color vocabulary reinforces the relationship system.


Appendix A — Decision Cross-References

Decision Relevance
D-018 Three-range sound model — source for indicator tier assignment.
D-047 Two-tier animation. Tier 2 NPC behaviors produce the sound events that trigger voice indicators.
D-048 Insert overlay visual language — indicators are part of the insert, not the world.
D-049 Z-level rendering stack — z-layer 6 for insert overlay.
D-059 Fog shader. Sound pings in fog are separate from sound indicators (fog layer concentric rings vs insert edge arrows).
D-070 Confrontation as cognitive vulnerability — danger indicators not suppressed during dialogue.

Appendix B — Quick Reference for Stig

Property Value
Z-layer 6 (insert overlay)
Neutral color #c8d0e0
Voice color #e8c547
Danger color #d45d5d
Max alpha 90%
Total visible duration (target) 2.5s
Total visible duration (current) 3.5s
Fade duration 1.0s ease-in
Deduplication Reset timer on same-tile re-trigger
Range alpha levels Close-medium 90% / standard 70% / far-medium 45%
Suppression: within LOS Yes
Suppression: insert off Yes
Suppression: danger + dialogue No — danger breaks through