diff --git a/server/playlist.js b/server/playlist.js index 90395f3..b87b034 100644 --- a/server/playlist.js +++ b/server/playlist.js @@ -41,7 +41,11 @@ class Playlist { static defaults() { return { crossfadeSeconds: 3, - behaviors: { staticChance: 0.5, wanderRadius: 60, wanderSpeed: 0.15, wanderVertical: 10, pathSpeed: 8, pathChance: 0.4 }, + /* Motion defaults are in centimetres and sized for the real display — a + * ~25-42cm table with ~4cm ghosts. They were originally set for a large + * open floor (60cm wander, 8cm/s walk, 5-10cm bob), which on a table reads + * as ghosts bouncing and sprinting off the edge. */ + behaviors: { staticChance: 0.5, wanderRadius: 2.5, wanderSpeed: 0.15, wanderVertical: 0.4, pathSpeed: 1.5, pathChance: 0.4, bobAmp: 0.3, bobHz: 0.4 }, rarity: { weights: { Common: 1.0, Rare: 0.5, Epic: 0.25, Legendary: 0.1 }, movementScale: { Common: 1.0, Rare: 1.0, Epic: 0.7, Legendary: 0.4 }, @@ -175,13 +179,20 @@ class Playlist { const k = this.scale(g); if (kind === 'path' && path) { return { type: 'path', points: path.points.map(p => [...p]), mode: path.mode || 'loop', - speed: (b.pathSpeed ?? 8) * k, phase: Math.random() * 1000, seed: Math.floor(Math.random() * 1e6) }; + speed: (b.pathSpeed ?? 1.5) * k, phase: Math.random() * 1000, seed: Math.floor(Math.random() * 1e6) }; } if (kind === 'wander') { - return { type: 'wander', radius: (b.wanderRadius ?? 60) * k, speed: (b.wanderSpeed ?? 0.15) * k, - vertical: (b.wanderVertical ?? 10) * k, seed: Math.floor(Math.random() * 1e6) }; + return { type: 'wander', radius: (b.wanderRadius ?? 2.5) * k, speed: (b.wanderSpeed ?? 0.15) * k, + vertical: (b.wanderVertical ?? 0.4) * k, seed: Math.floor(Math.random() * 1e6) }; } - return { type: 'static', bobAmp: (5 + Math.random() * 5) * k, bobHz: 0.3 + Math.random() * 0.3 }; + /* Idle bob, in cm. The server is authoritative here, so these defaults — + * not the client's — decide how much a static ghost floats. 3mm suits the + * real display (~4cm ghosts on a 25-42cm sheet); the jitter just keeps a + * group of statics from bobbing in lockstep. Tunable: behaviors.bobAmp/bobHz. */ + const amp = b.bobAmp ?? 0.3, hz = b.bobHz ?? 0.4; + return { type: 'static', + bobAmp: amp * (0.8 + Math.random() * 0.4) * k, + bobHz: hz * (0.85 + Math.random() * 0.3) }; } makeRecord(g, { spawn, path }, behavior, opts = {}) {