rp_10012/assets/Loading/scripts/manager/AudioManager.ts
TJH 30baaaf001
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 38s
音效修改
2025-10-09 11:39:16 +08:00

175 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<string, AudioClip> = 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<void> {
let promises = this._sfxAudioSources.map(source => {
return new Promise<void>((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();
}
}