经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
cocos creator主程入门教程(六)—— 消息分发
来源:cnblogs  作者:五邑隐侠  时间:2019/2/25 9:10:31  对本文有异议

五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑。本系列文章以TypeScript为介绍语言。

 

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

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

先定义监听回调类型

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

  

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

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

  

接口定义

  1. /**
  2. * 添加多次监听者,需要手动移除
  3. * @param msg
  4. * @param listener
  5. * @param target
  6. */
  7. public static addListener(msg: string, listener: NotifyListener, target?: any): void {}
  8.  
  9. /**
  10. * 添加单次监听者,事件触发后即移除
  11. * @param msg
  12. * @param listener
  13. * @param target
  14. */
  15. public static addOnceListener(msg: string, listener: NotifyListener, target?: any): void {}
  16.  
  17. /**
  18. * 移除指定消息指定的监听者
  19. * @param msg
  20. * @param listener
  21. */
  22. public static removeMsgListener(msg: string, listener: NotifyListener): void {}
  23.  
  24. /**
  25. * 移除指定消息所有监听者
  26. * @param msg
  27. */
  28. public static removeMsgAllListeners(msg: string): void {}
  29.  
  30. /**
  31. * 移除指定目标对指定消息的监听
  32. * @param msg
  33. * @param target
  34. */
  35. public static removeTargetMsgListen(msg: string, target: any): void {}
  36.  
  37. /**
  38. * 移除指定目标所有消息监听
  39. * @param target
  40. */
  41. public static removeTargetAllMsgListen(target: any): void {}
  42.  
  43. /**
  44. * 派发消息
  45. * @param msg
  46. * @param src
  47. * @param data
  48. */
  49. public static notify(msg: string, src: any, data: any): void {}

  

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

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

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

  

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

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

  

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

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

  

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

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

  

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

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

  

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

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

  

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

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

  

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

消息分发先说到这里,下一篇我们将介绍游戏业务层架构。

原文链接:http://www.cnblogs.com/niudanshui/p/10421757.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号