/** @format */ import {Data, Mgr} from '../GameControl' import {GAME_TYPE, LOCAL} from '../enums/Enum' import {ccUtils} from '../utils/ccUtils' import Bundle = cc.AssetManager.Bundle export class AudioManager { private bgmVolume = 1 private sfxVolume = 1 private bgmAudioID = -1 private bgmAudioClips: any private sfxAudioClips: any private sfxAudioClipsLoading: any private playedAudio = new Map() private curBgmUrl = null private curSfxUrl = null public isPlayRandomBgm: boolean = false // 随机播放背景音乐 private curRandom: any = -1 // 随机播放背景索引 private repeatPlayID: any = 0 // 背景音乐循环倒计时 private soundBundle: Bundle = null public async init() { cc.audioEngine.stopAll() cc.audioEngine.uncacheAll() this.bgmVolume = Mgr.storage.getNumber(LOCAL.bgmVolume, 1) this.sfxVolume = Mgr.storage.getNumber(LOCAL.sfxVolume, 1) this.bgmAudioClips = {} this.sfxAudioClips = {} this.sfxAudioClipsLoading = {} this.soundBundle = await ccUtils.getBundleAsync('sound') return this.soundBundle != null } public getUrl(url: string) { // return `sound/${url}` return url } /** * * @param url * @param isSameStop 再次播放当前音乐是否重新开始 默认重新开始 */ public playBGM(url: string, isSameStop = false) { this.isPlayRandomBgm = false this.curRandom = -1 const audioUrl = this.getUrl(url) if (isSameStop && this.curBgmUrl == audioUrl) { return } this.curBgmUrl = audioUrl this.stopLastBGM() if (this.bgmVolume > 0) { if (this.bgmAudioClips[audioUrl]) { cc.audioEngine.setMusicVolume(this.bgmVolume) this.bgmAudioID = cc.audioEngine.playMusic(this.bgmAudioClips[audioUrl], true) } else { this.soundBundle.load(audioUrl, cc.AudioClip, (err, audioClip: cc.AudioClip) => { if (!err) { this.bgmAudioClips[audioUrl] = audioClip cc.audioEngine.setMusicVolume(this.bgmVolume) this.bgmAudioID = cc.audioEngine.playMusic(audioClip, true) } }) } } } public playRandomBGM() { if (this.isPlayRandomBgm) { return } this.isPlayRandomBgm = true const audioUrl = this.getRandomUrl() this.curBgmUrl = audioUrl this.stopLastBGM() if (this.bgmVolume > 0) { let callback = () => { this.bgmAudioID = cc.audioEngine.playMusic(this.bgmAudioClips[audioUrl], false) const dur = cc.audioEngine.getDuration(this.bgmAudioID) cc.audioEngine.setMusicVolume(this.bgmVolume) this.repeatPlayID = setTimeout(() => { this.isPlayRandomBgm = false this.playRandomBGM() }, dur * 1000) } if (this.bgmAudioClips[audioUrl]) { callback() } else { this.soundBundle.load(audioUrl, cc.AudioClip, (err, audioClip: cc.AudioClip) => { if (!err) { this.bgmAudioClips[audioUrl] = audioClip callback() } }) } } } private getRandomUrl() { const ram = Math.randomRangeInt(1, 3) if (ram == this.curRandom) { // 同一首背景音乐 重新随机 return this.getRandomUrl() } this.curRandom = ram return this.getUrl(`common_bgm${ram}`) } public stopLastBGM() { if (this.repeatPlayID) { clearTimeout(this.repeatPlayID) } if (cc.audioEngine.isMusicPlaying()) { cc.audioEngine.stopMusic() } } public stopBGM() { this.curBgmUrl = '' this.stopLastBGM() } public playSFX(url: string, bundle?: Bundle, noStopCurSfx?: boolean, callFuc?: Function) { let audioUrl = this.getUrl(url) let audioUrlKey = audioUrl if (bundle) audioUrlKey += bundle.name if (this.curSfxUrl && !noStopCurSfx) { this.stopSFX(this.curSfxUrl) } if (!url) return this.curSfxUrl = url if (this.sfxVolume > 0) { if (this.sfxAudioClips[audioUrlKey]) { const playId = cc.audioEngine.playEffect(this.sfxAudioClips[audioUrlKey], false) cc.audioEngine.setEffectsVolume(this.sfxVolume) if (callFuc) { cc.audioEngine.setFinishCallback(playId, callFuc) } this.playedAudio.set(playId, audioUrl) } else { if (this.sfxAudioClipsLoading[audioUrlKey]) return this.sfxAudioClipsLoading[audioUrlKey] = true let tmp = bundle ? bundle : this.soundBundle let onCompleteFuc = (err, audioClip: cc.AudioClip) => { this.sfxAudioClipsLoading[audioUrlKey] = false if (!err) { this.sfxAudioClips[audioUrlKey] = audioClip const playId = cc.audioEngine.playEffect(audioClip, false) cc.audioEngine.setEffectsVolume(this.sfxVolume) if (callFuc) { cc.audioEngine.setFinishCallback(playId, callFuc) } this.playedAudio.set(playId, audioUrl) } } tmp.load(audioUrl, cc.AudioClip, onCompleteFuc) } } } public stopSFX(url: string) { const audioUrl = this.getUrl(url) let Ids = this.playedAudio.findKeyByValue(audioUrl) Ids.forEach(value => { if (value != -1) { cc.audioEngine.stop(value) this.playedAudio.delete(value) } }) } public setSFXVolume(v: number) { if (this.sfxVolume !== v) { Mgr.storage.set(LOCAL.sfxVolume, v) this.sfxVolume = v } } public setBGMVolume(v: number, force = false) { if (this.bgmAudioID >= 0) { if (v > 0) { cc.audioEngine.resume(this.bgmAudioID) } else { cc.audioEngine.pause(this.bgmAudioID) } } if (this.bgmVolume !== v || force) { Mgr.storage.set(LOCAL.bgmVolume, v) this.bgmVolume = v if (v > 0 && this.bgmAudioID >= 0) { cc.audioEngine.setVolume(this.bgmAudioID, v) } } } public pauseAll() { cc.audioEngine.pauseAll() } public stopAllEffects() { cc.audioEngine.stopAllEffects() } public resumeAll() { cc.audioEngine.resumeAll() } public onViewHide() { this.playedAudio.forEach((value, key) => { if (key != -1) { if (key == this.bgmAudioID) { cc.audioEngine.pause(key) } else { cc.audioEngine.stop(key) this.playedAudio.delete(key) } } }) } public onViewShow() { if (this.bgmAudioID > 0 && this.bgmVolume > 0) { cc.audioEngine.resume(this.bgmAudioID) } } }