cocos Creator自定义事件机制

项目中一直在使用cocos creator作为开发工具。之前使用的是cocos2d-x,用惯了notificationCenter,用了creator,发现没有这个东西,只能用js默认的on和emit用来设置事件监听和发送事件,但是,系统自带的on和emit有一个缺点,就是只能在当前脚本on和emit事件,这显然不够方便。就拿棋牌游戏打比方吧。例如,当前在设置页面,设置页面自己挂了一个脚本,然后,桌面是另一个脚本,当在设置中修改了桌面背景,如果想让桌面知道,但是,两者属于不同的脚本,这样用起来很不方便,所以,为了解决这个问题,楼主决定写一个消息中心。这里是实现该功能的GitHub地址。
下面来对说一下实现思路。首先,当在其他的脚本里调用MessageCenter.on方法的时候,调用方式是这样的:

MessageCenter.on('event1',this.eventFunc1.bind(this));

类似js自带的on方法,先设置监听的事件名称,然后,写上对应的处理方法。在这个on方法中,实现方式如下:

var bindFuncList = [];// 保存监听函数
function on(key,cbFunc){
    if (bindFuncList[key]){
        bindFuncList[key].push(cbFunc);
    }else {
        var ary = new Array();
        ary.push(cbFunc);
        bindFuncList[key] = ary;
    }
}

首先要定义一个数组,用来保存监听函数,由于多个脚本里面可能对同一个事件进行了监听,所以,这里应该说是一个二维数组,bindFuncList结构如下:

 [
 'event1':[func1,func2],
 'event2',[func3,func4]
 ]

首先判断bindFuncList[key]是否有这个数组,如果有的话,直接将新的监听函数push到里面去,如果没有,则New一个,然后再push。
然后是emit方法。

function emit(key,args){
    var ary = bindFuncList[key];
    if(ary){// 如果已经注册了事件,就直接发送消息
        for (var i in ary) {
            if (ary.hasOwnProperty(i)) {
                try {
                    ary[i].call(this,args);
                } catch (error) {
                    debugger;
                }
            }
        }
    }else {// 没有注册,先将要发送的消息保存,然后等待事件注册后,再一起emit
        if (emitList[key]){
            emitList[key].push(args);
        }else {
            var ary = new Array();
            ary.push(args);
            emitList[key] = ary;
        }
    }
}

当调用emit方法的时候,先从bindFuncList取出这个事件的array,如果有的话,就遍历来执行,同时,将参数传递过去,没有参数的话,默认会是undefined,不会出错。这里调用监听函数的时候,用到了一个call方法,这个是js的语法,不懂得人,可以去网上查一下相应的使用办法,就明白我的代码逻辑了。下面继续说这个emit方法。在调用emit的时候,如果发现,此时,对应的这个key,无法获取到ary的时候,我们会将emit的key和参数保存在另一个数组emitList中,这个数组的格式跟上一个二维数组的格式是类似的:

 [
 'event1':[args1,args2],
 'event2':[args3,args4];
 ]

key是事件名字,参数是个数组,里面是参数列表,如果多次emit这个事件,就以数组的形式保存起来。然后,下面有一个emitAll的方法,用来将所有的消息都emit出来。

下面说一下,为什么当获取不到ary的时候,要将key和args都保存起来,并且为什么要添加一个emitAll的方法。当我们在进行强联网游戏的时候,如果玩家正在和其他人一起玩游戏的时候,此时游戏崩溃了或者玩家将游戏进程杀死了。然后,玩家重新打开游戏,恢复场景的过程中,如果场景还没有完成初始化,就收到了网络回包,此时,还没有设置事件监听,因此UI层我发对事件进行处理,有可能会发生丢包的问题。出于这种考虑,当收到emit的时候,如果此时没有监听函数,就把数据保存起来,等到所有的监听设置好了之后,再调用一遍emitAll方法,来对这些消息进行统一的处理,防止丢包。其实对于这种问题,还有一个处理,就是当收到网络回包的时候,将所有的数据保存起来,然后,场景初始化的过程中,根据数据,来判断游戏、玩家出于什么状态,这样当然是更好的处理方式,但是有的时候,数据比较多,重连过程中,由于数据量大,所以要进行更多的判断逻辑。这个消息中心的在这里的处理,只是为了防止消息的丢包。

到这里,基本就完成了自定义的消息机制,如果有什么表达不清楚的地方,还请批评指正。

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