Mix
Everything RED DOT RISING is heard through.
Mix owns one deck of long-lived Audio sources under the sound mount, the
channel levels they are balanced at, and the verbs the rest of the game calls
to make a noise.
local Mix = require("game.sound.Mix")
Mix.ui("confirm") -- a menu sound: "move" | "confirm" | "back"
Mix.sting("win") -- an ending: "win" | "lose"
Mix.say("brief") -- Hoshi over the intercom; returns the line's seconds
The deck
Mix.attach(root) builds six sources under root and Mix.detach() takes
them away again; the Sound component calls both, so nothing else needs to.
| source | plays | channel |
|---|---|---|
snd_bed_rain | rain on the skylight, looping | ambient |
snd_bed_neon | the building's mains hum, looping | ambient |
snd_music | the night piece, looping | music |
snd_ui | menu one-shots | sfx |
snd_sting | the win and lose endings | sfx |
snd_voice | Hoshi's lines | voice |
Every source is 2D: the bed, the score and the intercom are the building itself, heard the same wherever the keeper is standing. Spatial sound belongs to the thing making it — a cat, a plate, the pointer.
The room changes as the tower is climbed
Mix.setFloor(n) tilts the bed per floor: the Lobby is deep inside the
building, so the rain arrives through glass and the mains hum is close; the
Rooftop Loft is out in the weather. Mix.setDawn(t) thins the score and
brings the rain forward as the night runs out. The Sound component drives
both from Core.state.
Ducking
Mix.duck(true) steps the bed and the score back; Mix.say and Mix.sting
do it themselves for as long as the clip lasts. Mix.tick(dt) walks the gain
there and back and is called once a frame by the Sound component — no timer,
no task, so a hot reload leaves nothing running.
The voice
Mix.LINES holds Hoshi's script: the words and the measured length of each
generated clip. Mix.say(id) plays the clip AND emits voice.line on
Core.bus carrying { id, text, seconds }, so the ui draws the words whether
or not the audio is there. A line with no clip is a quiet line, never a lost
one.
Reading it back
Mix.observe() reports the deck, the bed and score state, the floor, the
dawn, the duck gain, and what the mixer actually hears.
Scoped to this part · feeds back into the world's score.