// Sound effect dispatch: turns game sound events into positioned effect voices // (volume by distance to the camera, stereo panning along the screen's x axis). // The audio itself is rendered by audio.rs. use crate::audio; use crate::game::{Sfx, SfxEvent, SFX_ALL}; use macroquad::prelude::*; pub struct SoundBank { last: Vec, } impl SoundBank { pub fn new() -> SoundBank { SoundBank { last: vec![-1.0; SFX_ALL.len()] } } // minimum gap between two identical sounds (avoids a wall of noise) fn min_gap(sfx: Sfx) -> f64 { match sfx { Sfx::Dig | Sfx::GoldDig | Sfx::MeleeHit | Sfx::Shoot | Sfx::GateHit | Sfx::CoreHit => 0.08, Sfx::Claim | Sfx::Deposit | Sfx::DigDone => 0.12, _ => 0.03, } } // listener: camera target on the ground; right: screen-right direction on the ground; // hear: audible radius in tiles pub fn play(&mut self, ev: SfxEvent, listener: Vec2, right: Vec2, hear: f32, now: f64) { let i = ev.sfx.index(); if now - self.last[i] < Self::min_gap(ev.sfx) { return; } let mut vol = 1.0; let mut pan = 0.0; if let Some((wx, wy)) = ev.pos { let d = vec2(wx, wy) - listener; let f = 1.0 - ((d.length() - hear * 0.5) / hear).clamp(0.0, 1.0); if f <= 0.05 { return; } vol *= f; pan = (d.dot(right) / hear).clamp(-1.0, 1.0) * 0.7; } self.last[i] = now; audio::play_sfx(i, vol, pan); } }