import hitSound from '../../static/hit.mp3'; import shootSound from '../../static/shoot.mp3'; import clickSound from '../../static/click.mp3'; import ambientSound from '../../static/ambient.mp3'; import { OptionsHandler } from './options-handler'; export enum Sounds { hit = 'hit', shoot = 'shoot', click = 'click', } export abstract class SoundHandler { private static sounds: { [key in Sounds]: HTMLAudioElement }; private static isAmbientPlaying = false; private static ambientSound = new Audio(ambientSound); private static initialized = false; public static async initialize( onPlayKeypress: () => unknown = () => null, onPauseKeypress: () => unknown = () => null, ) { this.sounds = { [Sounds.hit]: await this.initializeSound(hitSound), [Sounds.shoot]: await this.initializeSound(shootSound), [Sounds.click]: await this.initializeSound(clickSound), }; await this.ambientSound.play(); this.ambientSound.muted = true; this.initialized = true; this.ambientSound.onpause = onPauseKeypress; this.ambientSound.onplay = onPlayKeypress; this.ambientSound.muted = false; this.ambientSound.volume = 0.5; this.ambientSound.loop = true; if (!this.isAmbientPlaying) { this.ambientSound.pause(); } } private static async initializeSound(hitSound: string): Promise { const sound = new Audio(hitSound); sound.muted = true; await sound.play(); sound.pause(); sound.muted = false; sound.currentTime = 0; return sound; } public static play(sound: Sounds, volume = 1, playbackRate = 1) { if (!this.initialized || !OptionsHandler.options.soundsEnabled) { return; } const audio = this.sounds[sound].currentTime > 0 ? (this.sounds[sound].cloneNode(true) as HTMLAudioElement) : this.sounds[sound]; audio.volume = Math.max(0, Math.min(1, volume)); audio.playbackRate = playbackRate; audio.play(); } public static playAmbient() { this.isAmbientPlaying = true; if (this.initialized) { this.ambientSound.play(); } } public static stopAmbient() { this.isAmbientPlaying = false; if (this.initialized) { this.ambientSound.pause(); } } }