摘要: 此文对cocos2d-x引擎中最具代表性,最能体现框架结构的几个类做了简单的介绍, 包括Director,Application, Renderer, EventDispatcher, Scheduler. 对于这些类, 也只对关系主要流程的方法做了介绍, 略过了容错代码和其它细节. 主要目的是让大家快速的对cocos2d-x引擎有一个全面笼统的认识, 也方便快速定位问题.



EventDispatcher

EventDispatcher,EventListener,Event之间的关系

  • EventDispatcher: 事件分发器, 相当于所有事件的中控中心. 管理着EventListener,当一个Event到来的时候决定CallBack的调用顺序。
  • Event ( EventTouch, EventKeyboard 等), 具体的事件数据,
  • EventListener ( EventListenerTouch, EventListenerKeyboard 等 ): 建立了Event到CallBack的映射关系, EventDispatcher 根据这种映射关系调用对应的 CallBack.

Event

Event有以下几种类型:

    enum class Type
{
TOUCH,
KEYBOARD,
ACCELERATION,
MOUSE,
FOCUS,
CUSTOM
};

Event最重要的属性就是type, 标识了它是那种类型的事件, 也决定了由哪个EventListner来处理它.

EventListener

EventListner有以下几种类型:

    enum class Type
{
UNKNOWN,
TOUCH_ONE_BY_ONE,
TOUCH_ALL_AT_ONCE,
KEYBOARD,
MOUSE,
ACCELERATION,
FOCUS,
CUSTOM
};

除了UNKNOWN, 跟Event::Type相比,Event::Type::TOUCH会同时被两种类型的EventListener处理: TOUCH_ONE_BY_ONE和TOUCH_ALL_AT_ONCE. 这两种EventListener分别处理单点触摸事件和多点触摸事件. 多说几句: 假如一个TouchEvent事件中有多个触摸点, 那么类型为 EventListener::Type::TOUCH_ONE_BY_ONE 的 EventListener 会把这个事件分解成若干个单点触摸事件来处理. 而类型为 EventListener::Type::TOUCH_ALL_AT_ONCE 的 EventListener 就是来处理多点触摸的, 会一次处理它.

其它几种类型都是一一对应的, 即一种Event::Type的Event会被对应类型的EventListener接受.

存放 EventListener 的地方

在EventDispatcher中, 它把以上7种 EventListener::Type 类型的 EventListner 放到7个队列中. 也就是在这样一个字段中:

std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;
  • EventListener::ListenerID : 每一种EventListener::Type有唯一的 EventListener::ListenerID. 其实通过这段代码 typedef std::string ListenerID; 可知: EventListener::ListenerID 就是简单 string, 就是一个名称而已.
  • EventListenerVector: 顾名思义, 就是一个 EventListener 的向量容器. 相对于普通的向量容器, 它增加了priority管理功能.

EventListener的fixedPriority

简单来说, 每个 EventListener 有自己的 fixedPriority 属性, 它是一个整数.

EventListener的遍历顺序

EventDispatcher 在抛发事件的时候, 会先处理 Event 的时候, 会优先遍历 fixedPriority 低的 EventListener, 调用它的 CallBack. 在某些条件下, 一个 Event 被一个 EventListener 处理之后, 会停止遍历其它的 EventListener. 反映到实战中就是: 你监听了某种事件, 这种事件也出发了, 但是对应的回调函数并没有被调用, 也就是被优先级更高的 EventListener 截获了.

如果 fixedPriority 一样呢? 按照什么顺序?

  1. fixedPriority 为0, 这个值是专门为 Scene Object 预留的. 即, 默认情况下, 绝大多数继承自 Node 的对象添加的普通事件监听器, 其 fixedPriority 都为0. 此时, Node 的 globalZOrder决定了优先级, 值越大, 越先被遍历到, 即在显示层中层级越高, 越先接受事件. 这在ui响应逻辑中也是合理的.
  2. fixedPriority 不为0, 那就按添加顺序.

Event在什么条件下会被优先级更高的EventListener截获?

  1. 对于 EventListenerTouchOneByOne, 它有一个字段: _needSwallow, 当它为 true 的时候, 如果它接受了某个 Event, 优先级更低的 EventListener 就接受不到了. 可以用 EventListenerTouchOneByOne::setSwallowTouches(bool needSwallow) 来改变它.
  2. 对于其它类型的 EventLIstener, 只有在显示调用了 Event::stopPropagation() 的时候, 才会中断遍历.

核心函数: EventDispatcher::dispatchEvent()

下面我们看看EventDispatcher最核心的函数:

void EventDispatcher::dispatchEvent(Event* event): 当有响应的事件到来的时候, 都会调用这个函数来通知监听了此事件的对象.

其实, 上面的介绍, 已经把这个函数里绝大部分逻辑都描述了,这里做一个最后的总结

事件抛发的简要流程如下:

  1. 检查 _listenerMap 中所有的EventListnerVector, 如果哪个容器的 EventListener 优先级顺序需要更新, 则重新排序
  2. 对于类型为 Event::Type::TOUCH 的事件, 则按照EventListener的遍历顺序遍历所有的 EventListener. 只有接受了 EventTouch::EventCode::BEGAN 事件的 EventListener, 才会收到其他类型的 EventTouch 事件.
  3. 对于其他类型的事件, 也按照EventListener的遍历顺序的顺序遍历对应的EventListener.

总结

Eventdispatcher 中的其它函数, 主要功能都是 添加EventListener, 删除EventListener等, 不做详细介绍.

总的来说, Eventdispatcher 是一个中转器:

  1. 事件的产生模块儿, 只关心自己构造正确的 Event, 调用 EventDispatcher::dispatchEvent(Event* event) 交给 EventDispatcher.
  2. 需要监听事件的模块儿, 只需调用 EventDispatcher::addEventListener(EventListener* listener) (或者它的其它变种)来注册自己作为监听者.
  3. 而 EventDispatcher 的作用是:
    1. 把特定类型的 Event 送给对应类型的 EventListener.
    2. 对于同一种 Event, 规定了事件送达的优先级.

Written with StackEdit.

[cocos2d-x]深入--几个代表性的类 (续)的更多相关文章

  1. [cocos2d-x]深入--几个代表性的类

    摘要: 此文对cocos2d-x引擎中最具代表性,最能体现框架结构的几个类做了简单的介绍, 包括Director,Application, Renderer, EventDispatcher, Sch ...

  2. Cocos2d 3.0继承自Sprite的类在addChild后出现故障

    当继承自Sprite的类被addChild到其它的Node里后出现例如以下图问题,说明没有调用父类Sprite::init()的方法.由于父类Sprite里的_textureAtlas须要初始化为nu ...

  3. 如何用boost::serialization去序列化派生模板类(续)

    在 如何用boost::serialization去序列化派生模板类这篇文章中,介绍了序列化派生类模板类, 在写測试用例时一直出现编译错误,调了非常久也没跳出来,今天偶然试了一下...竟然调了出来. ...

  4. .NET中的加密算法总结(自定义加密Helper类续)

    1.1.1 摘要 相信许多人都使用过.NET提供的加密算法,而且在使用的过程我们必须了解每种加密算法的特点(对称或非对称,密钥长度和初始化向量等等).我也看到过很多人写过.NET中加密算法总结,但我发 ...

  5. Cocos2d-x——CocosBuilder官方帮助文档翻译1 使用自定义类

    原创:请注明转载! 在Cocos2d-x中使用CocosBuilder 使用自定义类 CocosBuilder的使用方法是通过自定义类.在CocosBuilder中选中一个对象并在属性栏中输入自定义类 ...

  6. cocos2d-x实战 C++卷 学习笔记--第4章 字符串 __String类

    前言: <cocos2d-x实战C++卷>学习笔记.(cocos2d-x 是3.0版本) 介绍 cocos2d-x 通用的字符串类  __String . 使用cocos2d::__Str ...

  7. cocos2D(四)---- CCSprite

    在介绍CCSprite之前,先要理解游戏开发中的一个核心概念:精灵.精灵也称为游戏对象,它能够用来表示游戏中的不论什么物体,比方敌人.子弹.甚至是一个背景图片.一段文字.CCSprite能够说是在co ...

  8. [cocos2dx笔记013]一个使用CCRenderTexture创建动态纹理显示数字的类

    用CCLabelTTF显示的数字不好看.于是就想到用图片来代理.眼下网上的实现都是把每一个数字做一个CCSprite组合的方式. 可是我想.动态生成纹理的方式.没有就仅仅好自己手动写一个. 头文件 # ...

  9. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

随机推荐

  1. Squire – 简洁的 HTML5 富文本编辑器

    Squire 是一个简洁的 HTML5 富文本编辑器,它提供了强大的跨浏览器的标准化,超级轻巧灵活.它是建立在现在和未来并作为研究,因此并不支持那些古老的浏览器. 在线演示      源码下载 您可能 ...

  2. 总结的一些微信API接口

    本文给大家介绍的是个人总结的一些微信API接口,包括微信支付.微信红包.微信卡券.微信小店等,十分的全面,有需要的小伙伴可以参考下. 1. [代码]index.php <?php include ...

  3. EXCEL快速自动填充方法集锦

    EXCEL快速自动填充方法集锦 原文地址,转载请注明:http://www.cnblogs.com/croso/p/5396841.html 方法一: 名称框输入a1:a1000回车,1, ctrl+ ...

  4. Sharepoint学习笔记—习题系列--70-576习题解析 -(Q6-Q8)

    Question 6  You are designing a SharePoint 2010 solution that allows users to enter address informat ...

  5. Android 查看手机中所有进程

    真机测试的时候发现DDMS对进程的显示很不给力,一些进程管理工具又不显示包名. 所以就自己写了一个小程序,查看自己手机中的进程,显示当前时间和进程的包名: 程序运行截图: 布局: <Linear ...

  6. iOS开发之多媒体API (转载)

    视频格式可以分为适合本地播放的本地影像视频和适合在网络中播放的网络流媒体影像视频两大类.尽管后者在播放的稳定性和播放画面质量上可能没有前者 优秀,但网络流媒体影像视频的广泛传播性使之正被广泛应用于视频 ...

  7. android绘制view的过程

    1 android绘制view的过程简单描述  简单描述可以解释为:计算大小(measure),布局坐标计算(layout),绘制到屏幕(draw):            下面看看每一步的动作到底是 ...

  8. 【转】Android NFC学习笔记

    一:NFC的tag分发系统 如果想让android设备感应到NFC标签,你要保证两点 1:屏幕没有锁住 2:NFC功能已经在设置中打开 当系统检测到一个NFC标签的时候,他会自动去寻找最合适的acti ...

  9. (20160602)开源第三方学习之SDWebImage

    这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. 地址:https://github.com/rs/SDWebIm ...

  10. 【代码笔记】iOS-改变导航条标题的颜色为红色

    一,效果图. 二,代码. RootViewController.m - (void)viewDidLoad { [super viewDidLoad]; // Do any additional se ...