cocos creator 游戏背景音乐处理(音乐循环淡入淡出等)

在处理游戏背景音乐中遇到的问题,策划对于音乐播放提出新的想法。但由于目前周围没有人尝试过,所以自己摸索的来。

需求

cocos creator 游戏背景音乐处理(音乐循环淡入淡出等)_第1张图片

在同一场景音乐处理

一般同一场景是同一首背景音乐。
  现需求在同一场景(时代)内播放不同的音乐,在音乐配表中,同一场景加入新的音乐,每个音乐都带有一个cd字段,这个字段代表这首音乐播放剩余cd秒时,播放下一首音乐。相应的音乐资源会做淡入淡出处理。
  解决:做一个一直存在的定时器,用一个变量curAudio存当前音乐的path,用一个变量lastAudio存上一首音乐的path,获取到音乐资源的时长,在定时器内检测是否到达cd时间段,如在play下一首,cd完stop上一首,同时curAudio存当前音乐。

id = cc.audioEngine.play(audio, loop, volume);    //参数为:音乐,循环,音量
curAudio = audio;
cc.audioEngine.getDuration(id);                   //获取音频时长
cc.audioEngine.stop(lastAudio);                   //参数为:指定音乐
lastAudio = curAudio;

在场景切换时音乐处理

一般在场景切换时上一首音乐立马结束,紧接着播放下一首音乐。

cc.audioEngine.stopAll();
cc.audioEngine.play(audio, loop, volume);

现需求在场景切换时,音乐也需要切换到这个场景对应的音乐,这时候要考虑到切换场景时音乐的衔接。
  问题1:两个场景切换时上一个音乐的刚开始播放,下一场景音乐如何出现。
  解决:上一场景音乐加入淡出效果(设有一个cd),下一场景音乐紧接着淡入进来(设有一个cd)。
  问题2:两个场景切换时上一个音乐的播放到末尾已经资源上淡出再加上淡出,体验上会不会奇怪。
  解决:暂时以增加手动淡出时长来维护。


获取表数据整理结构

  1. 首先把表以场景ID为key,每个场景的音乐表数据为value,取到整个表的数据
table = this[this.TABLE.AGEBGM];
    this[this.TABLE.AGEBGM + this.EXFLAG] = {};
    for(i = 0; i < table.length; i++) {
        item = table[i];
        this[this.TABLE.AGEBGM + this.EXFLAG][item.age] = item;
    }
  1. 通过场景的ID,从表数据中取出单个场景的数据,并通过遍历这条数据,按自己需要的结构存储数据(定义一个数组,数组首位存储场景ID以待后用,然后通过循环单个判断音乐名称("bgm_"+j)、次播放提前量("cd"+j)是否存在,存在则单个(以key-value形式存储bgm和cd)按顺序存储)。
jsonTables.getEpochBgmTable = function (tid ) {
        var item = this[this.TABLE.AGEBGM + this.EXFLAG][tid];
        var bgm = new Array();
        if (item != null) {
            bgm[0] = tid;
            for (var j = 1; item["bgm_" + j] != null && item["cd_" + j] != null; j++){
                var tmp = new Array();
                tmp["bgm"] = item["bgm_" + j];
                tmp["cd"] = item["cd_" + j];
                bgm[j] = tmp;
            }
        }

        if (bgm != null){
            return bgm; 
        }
        return "";
    };
  1. 有了上面2的数据,通过传进来参数(场景ID)来取到相应场景的音乐数据。
  jsonTables.getEpochBgm = function (tid) {
        if (this.epochBgm == null || this.epochBgm[0] !== tid){
            this.epochBgm = this.getEpochBgmTable(tid);
        }
        return this.epochBgm;
    };

单个场景内循环播放音乐

  1. 遵循需求场景内循环播放音乐,且上一个音乐在最后cd秒时开始播放下一段音乐。
  2. 一个音乐播放函数。通过传进来的音乐名去音乐路径下取到这个资源。再播放。
    playBgMusic:function(name,loop){
        var audio = this.audios[name];
        if(!audio) return;

        this.bgAudioID = cc.audioEngine.play(audio, loop, this.bgVolume);
    }
  1. 初始化调用背景音乐函数,其中有个定时器里面循环判断。
  initBgm:function(epochId) {
        cc.audioEngine.stopAll();
        this.bgmTable = jsonTables.getEpochBgm(epochId);
        this.lastBgmId = null;
        this.lastTime = null;
        this.bgmIndex = 1;
        this.lastCD = 0;

        this.schedule(function () {
            this.playBgm()
        }, 0.1)
    }
  1. 这个是定时器里面调用的函数,具体来判断是不是要播放音乐了。首先如果初始化状态下this.lastBgmId为null那么进入播放音乐函数;或者拿到的这个数据表有>=2个的数据时(因为0位存的是场景ID,如果数据大于2个说明有多个音乐需要循环播放),再次判断上个音乐是否已经满足只剩cd秒,如果满足进入音乐播放函数。
  playBgm:function() {
        if(this.lastBgmId == null){
            this.playBgmByIndex();
        }else if (this.bgmTable.length > 2) {
            var time = cc.audioEngine.getCurrentTime(this.lastBgmId);
            if ( this.lastTime - time <= this.lastCD){
                this.playBgmByIndex();
            }
        }
    }
  1. 这个函数根据bgmIndex来取相应的音乐名,然后调用1 playBgMusic函数来播放。同时lastBgmId和lastCD存所播放音乐的id和cd,bgmIndex++,lastTime存所播放的音乐的总时长。
 playBgmByIndex: function ( ) {
            if (this.bgmTable == null){return;}
            if(this.bgmIndex >= this.bgmTable.length){
                this.bgmIndex = 1;
            }

            if (this.bgmTable.length === 2) {
                this.playBgMusic(this.bgmTable[this.bgmIndex].bgm, true);
            }else if (this.bgmTable.length > 2) {
                this.playBgMusic(this.bgmTable[this.bgmIndex].bgm, false);
            }else{
                return;
            }

            this.lastBgmId = this.bgAudioID;
            this.lastCD = this.bgmTable[this.bgmIndex].cd;
            this.bgmIndex += 1;
            this.lastTime = cc.audioEngine.getDuration(this.lastBgmId);
        },

场景切换时音乐更新

  1. 场景变化时,需要满足在变化的同时上一个场景音乐淡出,新场景音乐淡入。
      首先对于新场景的音乐数据通过id进行更新,然后lastBgmIdTmp保存下上个音乐的id(this.lastBgmId),在将this.lastBgmId赋空,这个操作是为了在3步骤函数定时器的下一帧时,通过4步骤函数中if(this.lastBgmId == null)这个判断调用音乐播放函数来播放新的场景音乐。
      然后定义两个变量lastVolume,curVolume存上个场景和新场景音量,this.bgmIndex置为1播放时新场景去取第一个资源。
      设置一个定时器,每1秒执行一次,执行5次,0.1秒后执行(防止上面新音乐未播放(上面音乐播放定时器是每0.1秒执行一次))。通过判断两个音乐的播放状态来对两个音乐音量进行控制,已达到旧音乐淡出新音乐淡入效果。
 changEpoch: function (epochId) {
        this.bgmTable = jsonTables.getEpochBgm(epochId);
        var lastBgmIdTmp = this.lastBgmId
        var lastVolume = 1;
        var curVolume = 0;
        this.lastBgmId = null;
        this.bgmIndex = 1;

        this.schedule(function () {
            var lastBgmState = cc.audioEngine.getState(lastBgmIdTmp);
            var curBgmState = cc.audioEngine.getState(this.lastBgmId);
            if (lastBgmState && lastVolume >= 0) {
                lastVolume -= 0.2;
                cc.audioEngine.setVolume(lastBgmIdTmp, lastVolume);
            }
            if(curBgmState && curVolume <= 1){
                curVolume += 0.2;
                cc.audioEngine.setVolume(this.lastBgmId, curVolume);
            }
        }, 1, 5, 0.1)
    },

audioEngine API

最后发现creator audioEngine提供了所需要的基本的API。

点击查看audioEngine API

你可能感兴趣的:(游戏开发)