58 lines
3.1 KiB
Text
58 lines
3.1 KiB
Text
|
|
-- DreamStack Pong Viewer (Spectator)
|
||
|
|
-- Watches the pong game live via streaming relay.
|
||
|
|
-- Renders the full visual court from streamed signal state.
|
||
|
|
--
|
||
|
|
-- Run with:
|
||
|
|
-- Tab 1: cargo run -p ds-stream (relay on :9100)
|
||
|
|
-- Tab 2: dreamstack dev examples/game-pong.ds (player)
|
||
|
|
-- Tab 3: dreamstack dev examples/pong-viewer.ds --port 3001 (viewer)
|
||
|
|
|
||
|
|
import { Badge } from "../registry/components/badge"
|
||
|
|
|
||
|
|
-- Connect to the pong game stream
|
||
|
|
let game = stream from "ws://localhost:9100/stream/pong"
|
||
|
|
|
||
|
|
view viewer = column [
|
||
|
|
text "👁️ Pong Spectator" { variant: "title" }
|
||
|
|
|
||
|
|
-- Score bar
|
||
|
|
row [
|
||
|
|
Badge { label: "LIVE 🔴", variant: "error" }
|
||
|
|
Badge { label: "P1: {game.score1}", variant: "info" }
|
||
|
|
Badge { label: "Rally: {game.rally}", variant: "warning" }
|
||
|
|
Badge { label: "AI: {game.score2}", variant: "error" }
|
||
|
|
]
|
||
|
|
|
||
|
|
-- ── Spectator Court ──
|
||
|
|
stack { style: "position:relative; width:600px; height:400px; background:linear-gradient(180deg,#0f172a,#1e293b); border:2px solid #334155; border-radius:16px; margin:0.5rem auto; overflow:hidden; box-shadow:0 0 40px rgba(99,102,241,0.15)" } [
|
||
|
|
-- Center line
|
||
|
|
column { style: "position:absolute; left:298px; top:0; width:4px; height:400px; background:repeating-linear-gradient(to bottom, #475569 0px, #475569 12px, transparent 12px, transparent 24px)" } []
|
||
|
|
|
||
|
|
-- Center circle
|
||
|
|
column { style: "position:absolute; left:260px; top:160px; width:80px; height:80px; border:2px solid #475569; border-radius:50%" } []
|
||
|
|
|
||
|
|
-- P1 paddle (blue, left)
|
||
|
|
column { style: "position:absolute; left:8px; width:12px; height:80px; background:linear-gradient(180deg,#818cf8,#6366f1); border-radius:6px; box-shadow:0 0 12px rgba(129,140,248,0.5); transition:top 0.1s", top: game.p1y } []
|
||
|
|
|
||
|
|
-- P2/AI paddle (red, right)
|
||
|
|
column { style: "position:absolute; left:580px; width:12px; height:80px; background:linear-gradient(180deg,#f87171,#ef4444); border-radius:6px; box-shadow:0 0 12px rgba(248,113,113,0.5); transition:top 0.1s", top: game.p2y } []
|
||
|
|
|
||
|
|
-- Ball (yellow glow)
|
||
|
|
column { style: "position:absolute; width:14px; height:14px; background:radial-gradient(circle,#fde68a,#f59e0b); border-radius:50%; box-shadow:0 0 16px #fbbf24,0 0 4px #fbbf24", top: game.ballY, left: game.ballX } []
|
||
|
|
|
||
|
|
-- Score overlay on court
|
||
|
|
row { style: "position:absolute; top:12px; left:0; width:100%; justify-content:center; gap:140px; pointer-events:none" } [
|
||
|
|
text "{game.score1}" { style: "font-size:56px; color:rgba(129,140,248,0.2); font-weight:900; font-family:monospace" }
|
||
|
|
text "{game.score2}" { style: "font-size:56px; color:rgba(248,113,113,0.2); font-weight:900; font-family:monospace" }
|
||
|
|
]
|
||
|
|
|
||
|
|
-- SPECTATING overlay
|
||
|
|
row { style: "position:absolute; bottom:12px; left:0; width:100%; justify-content:center; pointer-events:none" } [
|
||
|
|
text "SPECTATING" { style: "font-size:12px; color:rgba(255,255,255,0.15); letter-spacing:4px; font-weight:700" }
|
||
|
|
]
|
||
|
|
]
|
||
|
|
|
||
|
|
when game.paused -> text "⏸ Game is paused" { variant: "muted" }
|
||
|
|
text "View-only • no controls • game state received via relay" { variant: "muted" }
|
||
|
|
]
|