import { _decorator, AudioClip, AudioSource, Node, resources, director } from 'cc'; export class AudioManager { private static _instance: AudioManager = null; private _audioNode: Node = null; private _bgmAudioSource: AudioSource = null; // 专门用于背景音乐 private _sfxAudioSources: AudioSource[] = []; // 用于音效的多个AudioSource private _bgmVolume: number = 0.5; private _bgmClip: AudioClip = null; private _audioClips: Map = new Map(); private _isMuted: boolean = false; private _isPaused: boolean = false; static get instance(): AudioManager { if (!this._instance) { this._instance = new AudioManager(); } return this._instance; } init() { // 创建根节点 this._audioNode = new Node('AudioManager'); director.getScene().addChild(this._audioNode); // 创建BGM节点 let bgmNode = new Node('BGM'); this._audioNode.addChild(bgmNode); this._bgmAudioSource = bgmNode.addComponent(AudioSource); this._bgmAudioSource.playOnAwake = false; // 创建多个音效节点 for (let i = 0; i < 3; i++) { let sfxNode = new Node(`SFX_${i}`); this._audioNode.addChild(sfxNode); let sfxAudioSource = sfxNode.addComponent(AudioSource); sfxAudioSource.playOnAwake = false; this._sfxAudioSources.push(sfxAudioSource); } // 加载音频资源 this.loadAudioClips(); } private loadAudioClips() { resources.loadDir("audio", AudioClip, (err, clips) => { if (err) { console.error("加载音频资源失败:", err); return; } clips.forEach(clip => { this._audioClips.set(clip.name, clip); }); }); } playBGM(name: string, loop: boolean = true) { if (this._isMuted || !this._bgmAudioSource) return; this._bgmAudioSource.stop(); let clip = this._audioClips.get(name); if (!clip) { console.warn(`BGM ${name} 不存在`); return; } this._bgmClip = clip; this._bgmAudioSource.clip = clip; this._bgmAudioSource.loop = loop; this._bgmAudioSource.volume = this._bgmVolume; this._bgmAudioSource.play(); this._isPaused = false; } playSFX(name: string, volume: number = 1.0, loop: boolean = false) { if (this._isMuted) return; let clip = this._audioClips.get(name); if (!clip) { console.warn(`音效 ${name} 不存在`); return; } // 找到一个空闲的AudioSource let availableSource = this._sfxAudioSources.find(source => !source.playing); if (availableSource) { // 确保音量正确 availableSource.volume = volume; availableSource.loop = loop; availableSource.clip = clip; // 播放新音效 availableSource.play() } else { // 如果没有空闲的AudioSource,创建一个新的 let sfxNode = new Node(`SFX_${this._sfxAudioSources.length}`); this._audioNode.addChild(sfxNode); let newSource = sfxNode.addComponent(AudioSource); newSource.playOnAwake = false; newSource.volume = volume; newSource.loop = loop; newSource.clip = clip; this._sfxAudioSources.push(newSource); newSource.play() } } async stopAllSFX(): Promise { let promises = this._sfxAudioSources.map(source => { return new Promise((resolve) => { source.stop(); // 使用 setTimeout 确保音效停止 setTimeout(resolve, 100); }); }); await Promise.all(promises); } stopBGM() { if (this._bgmAudioSource) { this._bgmAudioSource.stop(); this._isPaused = false; } } pauseBGM() { if (this._bgmAudioSource && !this._isPaused) { this._bgmAudioSource.pause(); this._isPaused = true; } } resumeBGM() { if (!this._isMuted && this._bgmAudioSource && this._isPaused) { this._bgmAudioSource.play(); this._isPaused = false; } } setBGMVolume(volume: number) { this._bgmVolume = Math.max(0, Math.min(1, volume)); if (this._bgmAudioSource) { this._bgmAudioSource.volume = this._bgmVolume; } } setSFXVolume(volume: number) { // this._sfxVolume = Math.max(0, Math.min(1, volume)); // this._sfxAudioSources.forEach(source => { // source.volume = this._sfxVolume; // }); } setMute(muted: boolean) { this._isMuted = muted; if (muted) { this.stopBGM(); } else if (this._bgmClip) { this.playBGM(this._bgmClip.name); } } getMuted() { return this._isMuted; } // 清理资源 destroy() { if (this._audioNode) { this._audioNode.destroy(); } this._audioNode = null; this._bgmAudioSource = null; this._sfxAudioSources = []; this._audioClips.clear(); } }