详解CocosCreator消息分发机制


Posted in Javascript onApril 16, 2021

概述

本篇开始介绍游戏业务架构相关的内容。在游戏业务层,所有需要隔离的系统和模块间通信都可以通过消息分发解耦。例如网络返回通知、数据更新同步到界面等。

消息分发基于观察者模式设计。需要处理消息的地方向消息中心注册监听回调,派发消息时,调用消息中心的派发接口遍历该消息的监听队列,调用对应的回调方法。

具体方案

先定义监听回调类型

/**
 * 消息监听回调方法
 */
export type NotifyListener = (src: any, data: any) => void;

通过key-value方式保存监听队列

private static msg2listDict: Dictionary< string, Array<NotifyListenerInfo> > = new Dictionary< string, Array<NotifyListenerInfo> >();

接口定义

/**
 * 添加多次监听者,需要手动移除
 * @param msg
 * @param listener
 * @param target
 */
public static addListener(msg: string, listener: NotifyListener, target?: any): void {}
 
/**
 * 添加单次监听者,事件触发后即移除
 * @param msg
 * @param listener
 * @param target
 */
public static addOnceListener(msg: string, listener: NotifyListener, target?: any): void {}
 
/**
 * 移除指定消息指定的监听者
 * @param msg
 * @param listener
 */
public static removeMsgListener(msg: string, listener: NotifyListener): void {}
 
/**
 * 移除指定消息所有监听者
 * @param msg
 */
public static removeMsgAllListeners(msg: string): void {}
 
/**
 * 移除指定目标对指定消息的监听
 * @param msg
 * @param target
 */
public static removeTargetMsgListen(msg: string, target: any): void {}
 
/**
 * 移除指定目标所有消息监听
 * @param target
 */
public static removeTargetAllMsgListen(target: any): void {}
 
/**
 * 派发消息
 * @param msg
 * @param src
 * @param data
 */
public static notify(msg: string, src: any, data: any): void {}

在添加移除实现中,需要注意某消息可能正在派发。

对于一个消息新添加的监听者,应该在当前队列消息派发完后再派发,因此,添加一个待添加队列

private static listener2add: Array<NotifyListenerInfo> = [];

在添加监听者时做以下判断

// 该消息正在派发,放入待添加队列
if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
    NotifyCenter.listener2add.push(info);
    return;
}

同样在移除监听者时,可能正在派发消息,避免对队列的修改导致for循环异常,添加一个待移除队列,派发消息时,如果该监听者在移除队列则不派发。在消息派发完后再将其移出队列

private static listener2remove: Array<NotifyListenerInfo> = [];

在移除监听者时做以下判断

// 该消息正在派发,放入待移除队列
if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
    NotifyCenter.listener2remove.push(list[i]);
} else {
    list.splice(i, 1);
}

派发消息时遍历指定消息下的队列

// 队列不存在,不需要处理
let list = NotifyCenter.msg2listDict.get(msg);
if (!list) {
    return;
}
 
// 标记消息正在派发,多个消息可能同时在派发,同一消息可能标记多次
NotifyCenter.notifyMsgs.push(msg);
 
// 处理消息派发
for (let i = 0, n = list.length; i < n; i++) {
    NotifyCenter._dispatch(list[i], src, data, false);
}

派发消息时先判断是否在移除队列

// 在移除队列,不派发
if (NotifyCenter.listener2remove.indexOf(info) >= 0) {
    return;
}

当前队列派发完后检查待添加队列

// 处理待添加队列派发
for (let i = 0, n = msg2add.length; i < n; i++) {
    if (listener2add[i].msg == msg) {
        NotifyCenter._dispatch(listener2add[i], src, data, true);
    }
}

引入消息分发中心,隔离的系统、模块间通过消息监听和派发通信,避免互相引用耦合。

以上就是详解CocosCreator消息分发机制的详细内容,更多关于CocosCreator消息分发的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JQuery Tips(2) 关于$()包装集你不知道的
Dec 14 Javascript
jQuery 树形结构的选择器
Feb 15 Javascript
加载jQuery后$冲突的解决办法
Jul 09 Javascript
新发现一个骗链接的方法(js读取cookies)
Jan 11 Javascript
JavaScript实现表格点击排序的方法
May 11 Javascript
学习JavaScript设计模式之单例模式
Jan 19 Javascript
jQuery Dialog 取消右上角删除按钮事件
Sep 07 Javascript
vue 粒子特效的示例代码
Sep 19 Javascript
详解使用React全家桶搭建一个后台管理系统
Nov 04 Javascript
JavaScript 日期时间选择器一些小结
Apr 02 Javascript
详解JS深拷贝与浅拷贝
Aug 04 Javascript
JavaScript 实现下雪特效的示例代码
Sep 09 Javascript
CocosCreator入门教程之网络通信
Apr 16 #Javascript
JavaScript嵌入百度地图API的最详细方法
用javascript制作qq注册动态页面
利用javaScript处理常用事件详解
Apr 14 #Javascript
带你彻底理解JavaScript中的原型对象
Apr 14 #Javascript
游戏开发中如何使用CocosCreator进行音效处理
详解CocosCreator项目结构机制
You might like
Laravel 4 初级教程之视图、命名空间、路由
2014/10/30 PHP
php简单实现快速排序的方法
2015/04/04 PHP
PHP读取大文件的几种方法介绍
2016/10/27 PHP
读jQuery之十三 添加事件和删除事件的核心方法
2011/08/23 Javascript
js实现瀑布流的一种简单方法实例分享
2013/11/04 Javascript
jQuery向后台传入json格式数据的方法
2015/02/13 Javascript
js实现的二分查找算法实例
2016/01/21 Javascript
点击按钮出现60秒倒计时的简单js代码(推荐)
2016/06/07 Javascript
Angular.js自定义指令学习笔记实例
2017/02/24 Javascript
使用bootstrap-paginator.js 分页来进行ajax 异步分页请求示例
2017/03/09 Javascript
React中jquery引用的实现方法
2017/09/12 jQuery
mui上拉加载更多下拉刷新数据的封装过程
2017/11/03 Javascript
JQuery判断radio单选框是否选中并获取值的方法
2019/01/17 jQuery
vue实现鼠标移入移出事件代码实例
2019/03/27 Javascript
[01:02]DOTA2上海特锦赛SHOWOPEN
2016/03/25 DOTA
Python里隐藏的“禅”
2014/06/16 Python
Python中矩阵库Numpy基本操作详解
2017/11/21 Python
使用python编写简单的小程序编译成exe跑在win10上
2018/01/15 Python
python 安装impala包步骤
2020/03/28 Python
Python多线程的退出控制实现
2020/08/10 Python
Python调用飞书发送消息的示例
2020/11/10 Python
利用css3径向渐变做一张优惠券的示例
2018/03/22 HTML / CSS
HTML5画渐变背景图片并自动下载实现步骤
2013/11/18 HTML / CSS
HTML5通过调用canvas对象的getContext()方法来获取绘图环境
2014/06/23 HTML / CSS
新加坡鲜花速递/新加坡网上花店:Ferns N Petals
2020/08/29 全球购物
Can a struct inherit from another class? (结构体能继承类吗)
2014/07/22 面试题
雪山饭庄的创业计划书范文
2014/01/18 职场文书
协议书与合同的区别
2014/04/18 职场文书
企业职业病防治方案
2014/05/29 职场文书
合作意向书
2014/07/30 职场文书
法人代表身份证明书及授权委托书
2014/09/16 职场文书
2014年档案管理员工作总结
2014/12/01 职场文书
解决redis sentinel 频繁主备切换的问题
2021/04/12 Redis
Netty结合Protobuf进行编解码的方法
2021/06/26 Java/Android
Redis 常见使用场景
2021/08/30 Redis
SQL CASE 表达式的具体使用
2022/03/21 SQL Server