Files
org_web/assets/scripts/games/two-rivers/systems/audio.js
gitea-actions 08516fda14
All checks were successful
Build Org Website / build (push) Successful in 45s
Serve Two Rivers modules with production MIME type
2026-08-11 13:40:14 +01:00

79 lines
2.3 KiB
JavaScript

// Native ES module served with the production JavaScript MIME type.
export class AudioDirector {
constructor(records, getSettings) {
this.getSettings = getSettings;
this.records = records;
this.sounds = new Map();
this.music = null;
this.ambience = null;
this.unlocked = false;
records.forEach((record) => {
this.sounds.set(record.id, new window.Howl({
src: record.urls || [record.url],
loop: record.type !== "sfx",
preload: record.type === "sfx",
volume: 0
}));
});
document.addEventListener("visibilitychange", () => {
if (document.hidden) window.Howler?.mute(true);
else if (this.getSettings().sound) window.Howler?.mute(false);
});
}
unlock() {
this.unlocked = true;
window.Howler?.ctx?.resume?.();
this.sync();
}
sync() {
const settings = this.getSettings();
window.Howler.volume(settings.masterVolume);
window.Howler.mute(!settings.sound);
if (this.music) this.sounds.get(this.music)?.volume(settings.musicVolume);
if (this.ambience) this.sounds.get(this.ambience)?.volume(settings.ambienceVolume * 0.35);
}
playLocation(music, ambience) {
if (!this.unlocked) return;
this.crossfade("music", music);
this.crossfade("ambience", ambience);
}
crossfade(channel, nextId) {
const currentId = this[channel];
if (currentId === nextId) return;
const settings = this.getSettings();
const target = channel === "music" ? settings.musicVolume : settings.ambienceVolume * 0.35;
if (currentId && this.sounds.has(currentId)) {
const old = this.sounds.get(currentId);
old.fade(old.volume(), 0, 500);
window.setTimeout(() => old.stop(), 520);
}
this[channel] = nextId;
const next = this.sounds.get(nextId);
if (next) {
next.volume(0);
if (!next.playing()) next.play();
next.fade(0, target, 700);
}
}
sfx(id) {
if (!this.unlocked || !this.getSettings().sound) return;
const sound = this.sounds.get(id);
if (sound) {
sound.volume(this.getSettings().sfxVolume);
sound.play();
}
}
duck(active) {
if (!this.music) return;
const sound = this.sounds.get(this.music);
const volume = this.getSettings().musicVolume * (active ? 0.45 : 1);
sound?.fade(sound.volume(), volume, 250);
}
}