123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- import { _decorator, Component, Node, AudioSourceComponent, loader, AudioClip, IsPowerOf2, url, instantiate, TERRAIN_HEIGHT_BASE } from 'cc';
- const { ccclass, property } = _decorator;
- @ccclass('SoundManager')
- export class SoundManager extends Component {
- /**
- * 背景音乐通道
- */
- private musicSoundChannel:AudioChannel;
- /**
- * 固定通道
- */
- private soundChannelMap:Map<string,AudioChannel>;
- /**
- * 重复利用通道
- */
- private recycleSoundChannelList:AudioChannel[];
- private recycleSoundChannelPool:AudioChannel[];
- onLoad():void{
- SoundManager.instance=this;
- this.soundChannelMap=new Map<string,AudioChannel>();
- this.recycleSoundChannelList=[];
- this.recycleSoundChannelPool=[];
- }
- start () {
- //背景音乐通道
- this.musicSoundChannel=new AudioChannel();
- this.musicSoundChannel.aSComponent=this.addComponent(AudioSourceComponent);
- //最大重复利用通道4个
- let channel:AudioChannel;
- for (let index = 0; index < 6; index++) {
- channel=new AudioChannel();
- channel.aSComponent=this.addComponent(AudioSourceComponent);
- this.recycleSoundChannelPool.push(channel);
- }
- }
- public PlayMusic(soundPath:string):void{
- this.musicSoundChannel.Play(soundPath,true);
- }
- /**
- * 固定通道播放音效
- * @param channel 通道
- * @param soundPath 音效地址
- * @param isLoop 是否循环播放
- * @param force 是否在相同音频的情况下强制从头开始播放
- */
- public PlaySound(channel:string,soundPath:string,isLoop:boolean=false,force:boolean=false):void{
- let audioChannel:AudioChannel;
- if(this.soundChannelMap.has(channel)==false){
- audioChannel=new AudioChannel();
- audioChannel.aSComponent=this.addComponent(AudioSourceComponent);
- this.soundChannelMap.set(channel,audioChannel);
- }else{
- audioChannel=this.soundChannelMap.get(channel);
- }
- audioChannel.Play(soundPath,isLoop,force);
- }
- /**
- * 清理通道
- * @param channel
- */
- public ClearSound(channel:string):void{
- if(this.soundChannelMap.has(channel)==false){
- return;
- }
- let audioChannel:AudioChannel=this.soundChannelMap.get(channel);
- audioChannel.Dispose();
- this.soundChannelMap.delete(channel);
- }
- /**
- * 停止某个固定通道的音效
- * @param channel
- */
- public StopSound(channel:string):void{
- if(this.soundChannelMap.has(channel)==false){
- return;
- }
- let audioChannel:AudioChannel=this.soundChannelMap.get(channel);
- audioChannel.Stop();
- }
- /**
- * 某个固定频道是否在播放中
- * @param channel
- */
- public ChannelIsPlaying(channel:string):boolean{
- if(this.soundChannelMap.has(channel)==false){
- return false;
- }
- let audioChannel:AudioChannel=this.soundChannelMap.get(channel);
- return audioChannel.isPlaying;
- }
- /**
- * 通道播放音效
- * @param soundPath 音效地址
- */
- public PlaySoundRecycleChannel(soundPath:string):void{
- let audioChannel:AudioChannel;
- //检测是否有已经播放完成的通道
- for (let index = 0; index < this.recycleSoundChannelList.length; index++) {
- const element = this.recycleSoundChannelList[index];
- if(element.isPlaying==false){
- this.recycleSoundChannelPool.push(element);
- this.recycleSoundChannelList.splice(index,1);
- }
- }
- //如果池中没有,则不播放该音效!
- if(this.recycleSoundChannelPool.length==0){
- return;
- }
- audioChannel=this.recycleSoundChannelPool.pop();
- this.recycleSoundChannelList.push(audioChannel);
- //标记为被占有
- audioChannel.Play(soundPath,false);
- }
- // update (deltaTime: number) {
- // // Your update function goes here.
- // }
- private static instance:SoundManager;
- public static get single():SoundManager{
- return this.instance;
- }
- }
- class AudioChannel{
- /**
- * 音频资源
- */
- private static audioClipMap:Map<string,AudioClip>=new Map<string,AudioClip>();
- aSComponent:AudioSourceComponent;
- private soundUrl:string;
- private isLoop:boolean;
- private force:boolean;
- /**
- * 0 空闲 1加载中 2播放中
- */
- private state:number=0;
- constructor(){
- }
- Play(soundUrl:string,isLoop:boolean,force:boolean=false):void{
- if(this.soundUrl==soundUrl&&this.state==1){
- return;
- }
- this.soundUrl=soundUrl;
- this.isLoop=isLoop;
- this.force=force;
- this.state=1;
- let key:string=url.raw("resources/"+this.soundUrl);
- if(AudioChannel.audioClipMap.has(key)){
- let clip:AudioClip=AudioChannel.audioClipMap.get(key);
- console.log("播放音频缓存!");
- this.__play(clip);
- }else{
- loader.loadRes(this.soundUrl,AudioClip,this.audioLoadComplete.bind(this));
- }
- }
- private audioLoadComplete(err:Error,asset:AudioClip):void{
- if(err){
- console.error("加载音乐错误!");
- return;
- }
- let key:string=asset.nativeUrl.replace(asset["_native"],"");
- AudioChannel.audioClipMap.set(key,asset);
- if(this.state==0){
- return;
- }
- this.__play(asset);
- }
- private __play(audioClip:AudioClip):void{
- this.state=2;
- if(this.aSComponent==null){
- return;
- }
- if(this.aSComponent.clip!=audioClip){
- this.aSComponent.stop();
- this.aSComponent.clip=audioClip;
- }
- this.aSComponent.loop=this.isLoop;
- if(this.force){
- this.aSComponent.currentTime=0;
- }
- this.aSComponent.play();
- }
- Stop():void{
- this.state=0;
- this.soundUrl=null;
- this.aSComponent.stop();
- }
- Dispose():void{
- this.soundUrl=null;
- this.aSComponent.destroy();
- this.aSComponent=null;
- }
- get isPlaying():boolean{
- return this.state>0;
- }
- }
|