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 Creator自定义事件机制

未经允许不得转载:cocos集中营 » cocos Creator自定义事件机制
微信公众号:zs40086
免vip看全网视频,抢先福利电影啥都有!
10000人已关注
分享到:
赞(1) 打赏