Skip to content

feat: Ambient Presence Map — Shadow silhouettes, Reveal Pulse, Radio Radius, Vibe Match AR, Digital Drink, Mystery Box#5

Draft
cloudygetty-ai wants to merge 2 commits into
mainfrom
claude/ambient-presence-map-qbHjf
Draft

feat: Ambient Presence Map — Shadow silhouettes, Reveal Pulse, Radio Radius, Vibe Match AR, Digital Drink, Mystery Box#5
cloudygetty-ai wants to merge 2 commits into
mainfrom
claude/ambient-presence-map-qbHjf

Conversation

@cloudygetty-ai

Copy link
Copy Markdown
Owner

Summary

Six interlocking social-discovery systems under src/features/ambientPresence/, fully self-contained and importable from a single barrel (src/features/ambientPresence/index.ts).

What was built

System Files Description
Shadow Map AmbientPresenceMap, SilhouettePin Users render as geometry silhouettes offset by a randomised shadowOffset — exact position never exposed
Reveal Pulse RevealPulseEngine, RevealPulseLayer 5-minute cycle fires a 10-second window where silhouettes sharpen and the map breathes a gold overlay
Radio Radius RadioRadiusService computeRadioMatches returns all users within 300 world units; selectVibeMatch scores genre + BPM + proximity
Vibe Match AR VibeMatchGlow Breathing concentric gold rings beneath the highest-scored silhouette — no UI chrome, purely cinematic
Digital Drink DigitalDrinkService, DigitalDrinkPanel Song-length (~3.5 min) token invitation; auto-melts on expiry; OutgoingTokenPanel + IncomingTokenPanel share one Deep Noir stylesheet
Mystery Box MysteryBoxService, MysteryBoxBanner Hourly clue drops surface a random interest from a nearby user without revealing identity

Architecture

  • One Zustand store (useAmbientPresenceStore) owns all state; mount() / unmount() manage timers cleanly
  • RevealPulseEngine is a plain class — interval + timeout, no React dependency, fully stoppable
  • Service layer is pure functions — no side-effects, trivially testable
  • Components follow the same viewport-coordinate pattern as GameMap (worldPos - viewportOffset = screenPos)

Palette — Deep Noir

Token Hex Usage
Background #0A0810 Map ground, panel fill
Gold #C0A060 Reveal glow, borders, CTA button, vibe match ring
Lavender #7B4F8A Genre label, secondary text, decline button
Velvet crimson #8B1A2E Mystery Box left border accent
Warm off-white #E8E0D0 Primary body text

Test plan

  • RevealPulseEngine — 6 tests covering interval fire, end-timeout, stop cancellation, fireImmediate
  • DigitalDrinkService — 12 tests covering createToken, resolveToken (all four accept/expire combinations), isMelted, timeRemainingMs, progressFraction
  • ambientPresenceStore — 14 tests covering radio match computation, pulse reveal/unrevealing, token send/accept/decline/tick, mystery clue generation
  • All 107 pre-existing tests remain green — 142 total, 0 regressions
  • tsc --noEmit clean

https://claude.ai/code/session_01KaZr9b1uR49iyrm26586SW


Generated by Claude Code

claude added 2 commits May 8, 2026 13:46
Six interlocking systems, all under src/features/ambientPresence/:

- Shadow Map (AmbientPresenceMap + SilhouettePin): users render as
  anonymised silhouettes offset by a randomised shadowOffset; exact
  positions are never exposed on the map surface.

- Reveal Pulse (RevealPulseEngine + RevealPulseLayer): every 5 minutes
  a 10-second window fires where silhouettes sharpen, labels appear,
  and the map breathes a gold overlay. Engine is timer-driven and
  fully stoppable to prevent leaks on unmount.

- Radio Radius (RadioRadiusService): computeRadioMatches returns all
  users within 300 world units sorted by distance; selectVibeMatch
  scores genre overlap + BPM proximity + closeness to pick the single
  best AR target.

- Vibe Match AR (VibeMatchGlow): breathing concentric gold rings
  placed beneath the highest-scored silhouette — cinematic, not
  technical.

- Digital Drink (DigitalDrinkService + DigitalDrinkPanel): token
  invitation system with a 3.5-minute song-length timer. Token
  auto-melts on expiry; accept/decline resolve immediately. Both
  outgoing and incoming panels share one StyleSheet, Deep Noir palette.

- Mystery Box (MysteryBoxService + MysteryBoxBanner): hourly clue
  drops surface a random interest from a nearby user without revealing
  who. Banner fades in sharply, holds 8 s, then dims to a persistent
  40% until the next drop.

State is managed in a single Zustand store (useAmbientPresenceStore)
with mount/unmount lifecycle hooks that own all timers. 35 new tests
cover all pure-logic modules; 0 regressions (142 total, was 107).

https://claude.ai/code/session_01KaZr9b1uR49iyrm26586SW
Routes / → demo.html so the browser game is served at the project root.

https://claude.ai/code/session_01KaZr9b1uR49iyrm26586SW
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants