pinball/assets/_Game/Scripts/Manager/AudioManager.ts

145 lines
3.6 KiB
TypeScript

import { _decorator, AudioClip, AudioSource, sys } from 'cc';
import 'howler';
export class SfxSource {
private _source: AudioSource;
public get playing() {
return this._source.playing;
}
public get loop() {
return this._source.loop;
}
public set loop(value: boolean) {
this._source.loop = value;
}
private _volume = 1;
public get volume() {
return this._volume;
}
public set volume(value: number) {
this._volume = value;
if (!this.mute) {
this._source.volume = value;
}
}
private _mute = false;
public get mute() {
return this._mute;
}
public set mute(value: boolean) {
if (value) {
this._source.volume = 0;
} else {
this._source.volume = this.volume;
}
this._mute = value;
}
constructor(audioClip: AudioClip) {
this._source = new AudioSource();
this._source.playOnAwake = false;
this._source.clip = audioClip;
}
public play() {
if (!this.loop) {
if (this.playing) {
this._source.playOneShot(this._source.clip, this.mute ? 0 : this.volume);
return;
}
this._source.play();
} else {
if (!this.playing) this._source.play();
}
}
public stop() {
this._source.stop();
}
}
export default class AudioManager {
private static _audioSourcesSfx: Map<AudioClip, SfxSource> = new Map();
private static _audioSourceBgm: Howl;
private static _isMute: boolean = false;
public static get mute() {
return this._isMute;
}
public static toggleMute(): boolean {
this._isMute = !this._isMute;
this.setMute(this._isMute);
return this._isMute;
}
public static setMute(mute: boolean) {
this._isMute = mute;
this._audioSourceBgm.mute(this._isMute);
this._audioSourcesSfx.forEach((source) => {
source.mute = this._isMute;
});
}
public static playBGM(audio: AudioClip, opts?: { volume?: number; loop?: boolean; rate?: number }) {
this._audioSourceBgm?.stop();
this._audioSourceBgm = new Howl({
src: audio.nativeUrl,
loop: true,
mute: this._isMute,
...opts,
});
this._audioSourceBgm.play();
}
public static setPlayRateBGM(rate: number) {
this._audioSourceBgm.rate(rate);
}
public static playSfx(audioClip: AudioClip, opts?: { volume?: number; loop?: boolean }) {
let soundSource = this._audioSourcesSfx.get(audioClip);
const config = {
volume: 1,
loop: false,
...opts,
};
if (soundSource) {
soundSource.volume = config.volume;
soundSource.loop = config.loop;
soundSource.mute = this._isMute;
soundSource.play();
return;
}
soundSource = new SfxSource(audioClip);
soundSource.loop = config.loop;
soundSource.volume = config.volume;
soundSource.mute = this._isMute;
this._audioSourcesSfx.set(audioClip, soundSource);
soundSource.play();
}
public static stopBgm() {
this._audioSourceBgm.stop();
}
public static stopSfx(audioClip: AudioClip) {
this._audioSourcesSfx.get(audioClip).stop();
}
public static stopAllSfxLoop() {
this._audioSourcesSfx.forEach((sfx) => sfx.stop());
}
public static findAudioSourcesSfx(audioClip: AudioClip): SfxSource {
return this._audioSourcesSfx.get(audioClip);
}
}