feat: Add SoundManager for bg music and opendoor sfx
This commit is contained in:
115
src/view/SoundManager.js
Normal file
115
src/view/SoundManager.js
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
export class SoundManager {
|
||||
constructor() {
|
||||
this.musicVolume = 0.3; // Default volume (not too loud)
|
||||
this.sfxVolume = 0.5;
|
||||
this.currentMusic = null;
|
||||
this.isMuted = false;
|
||||
|
||||
// Asset Library
|
||||
this.assets = {
|
||||
music: {
|
||||
'exploration': '/assets/music/ingame/Abandoned_Ruins.mp3'
|
||||
},
|
||||
sfx: {
|
||||
'door_open': '/assets/sfx/opendoor.mp3'
|
||||
}
|
||||
};
|
||||
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the audio context if needed (browser restriction handling)
|
||||
* Can be called on the first user interaction (click)
|
||||
*/
|
||||
init() {
|
||||
if (this.initialized) return;
|
||||
this.initialized = true;
|
||||
console.log("[SoundManager] Audio System Initialized");
|
||||
}
|
||||
|
||||
playMusic(key) {
|
||||
if (this.isMuted) return;
|
||||
|
||||
const url = this.assets.music[key];
|
||||
if (!url) {
|
||||
console.warn(`[SoundManager] Music track not found: ${key}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// If same track is playing, do nothing
|
||||
if (this.currentMusic && this.currentMusic.src.includes(url) && !this.currentMusic.paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop current
|
||||
this.stopMusic();
|
||||
|
||||
// Start new
|
||||
this.currentMusic = new Audio(url);
|
||||
this.currentMusic.loop = true;
|
||||
this.currentMusic.volume = this.musicVolume;
|
||||
|
||||
// Handle autoplay promises
|
||||
const playPromise = this.currentMusic.play();
|
||||
if (playPromise !== undefined) {
|
||||
playPromise.catch(error => {
|
||||
console.log("[SoundManager] Autoplay prevented. Waiting for user interaction.");
|
||||
// We can add a one-time click listener to window to resume if needed
|
||||
const resume = () => {
|
||||
this.currentMusic.play();
|
||||
window.removeEventListener('click', resume);
|
||||
window.removeEventListener('keydown', resume);
|
||||
};
|
||||
window.addEventListener('click', resume);
|
||||
window.addEventListener('keydown', resume);
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`[SoundManager] Playing music: ${key}`);
|
||||
}
|
||||
|
||||
stopMusic() {
|
||||
if (this.currentMusic) {
|
||||
this.currentMusic.pause();
|
||||
this.currentMusic.currentTime = 0;
|
||||
this.currentMusic = null;
|
||||
}
|
||||
}
|
||||
|
||||
setMusicVolume(vol) {
|
||||
this.musicVolume = Math.max(0, Math.min(1, vol));
|
||||
if (this.currentMusic) {
|
||||
this.currentMusic.volume = this.musicVolume;
|
||||
}
|
||||
}
|
||||
|
||||
toggleMute() {
|
||||
this.isMuted = !this.isMuted;
|
||||
if (this.isMuted) {
|
||||
if (this.currentMusic) this.currentMusic.pause();
|
||||
} else {
|
||||
if (this.currentMusic) this.currentMusic.play();
|
||||
}
|
||||
return this.isMuted;
|
||||
}
|
||||
|
||||
playSound(key) {
|
||||
if (this.isMuted) return;
|
||||
|
||||
const url = this.assets.sfx[key];
|
||||
if (!url) {
|
||||
console.warn(`[SoundManager] SFX not found: ${key}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const audio = new Audio(url);
|
||||
audio.volume = this.sfxVolume;
|
||||
// Fire and forget, but catch errors
|
||||
audio.play().catch(e => {
|
||||
// Check if error is NotAllowedError (autoplay) - silently ignore usually for SFX
|
||||
// or log if needed
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user