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



EventDispatcher

EventDispatcher,EventListener,Event之间的关系

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

Event

Event有以下几种类型:

  1. enum class Type
  2. {
  3. TOUCH,
  4. KEYBOARD,
  5. ACCELERATION,
  6. MOUSE,
  7. FOCUS,
  8. CUSTOM
  9. };

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

EventListener

EventListner有以下几种类型:

  1. enum class Type
  2. {
  3. UNKNOWN,
  4. TOUCH_ONE_BY_ONE,
  5. TOUCH_ALL_AT_ONCE,
  6. KEYBOARD,
  7. MOUSE,
  8. ACCELERATION,
  9. FOCUS,
  10. CUSTOM
  11. };

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

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

存放 EventListener 的地方

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

  1. 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. 此时, NodeglobalZOrder决定了优先级, 值越大, 越先被遍历到, 即在显示层中层级越高, 越先接受事件. 这在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. Treed – 基于拖放 操作的,强大的树形编辑器

    Treed 是一个功能强大的树型编辑组件.Treed 使用 MVC 模式,简单的构造可以帮助你轻松创建一个完全不同的树形视图.您也可以创建自己的“节点”类,如果你想要做的不仅仅是单一的文本输入. 您可 ...

  2. 27款后台管理页面设计 DIV+CSS+JS

    -----------. 演示: http://www.websjy.com/club/websj ... _61040268/index.htm http://www.websjy.com/club ...

  3. Android自定义ScrollView分段加载大文本数据到TextView

    以下内容为原创,转载时请注明链接地址:http://www.cnblogs.com/tiantianbyconan/p/3311658.html 这是我现在碰到的一个问题,如果需要在TextView中 ...

  4. C语言中的运算符

    1. 在C语言中运算符包括:算术运算符.关系运算符.赋值运算符.逻辑运算符 2.用运算符把变量.常量连接起来的式子就是表达式 3.我们阅读一个表达式,从表达式的功能和表达式的值来看 4. 算术运算符和 ...

  5. 网络编程--ASI--(ASIHTTPRequest)介绍

    ASIHTTPRequest 虽然是明日黄花,但是还是稍微归纳一下,理清思路,知道这个曾经的她都能干嘛. 1. ASI基于底层的 CFNetworking 框架,运行效率很高. 2. 黄金搭档:ASI ...

  6. winform ListView应用之分组、重绘图标、网格线 (c# .net winform)

    最近在winform应用中需要用到可分组的数据列表功能,DataGridView默认没有提供分组的功能,而OutlookGrid(http://www.codeproject.com/KB/grid/ ...

  7. HashMap vs TreeMap vs Hashtable vs LinkedHashMap

    Map是一个重要的数据结构,本篇文章将介绍如何使用不同的Map,如HashMap,TreeMap,HashTable和LinkedHashMap. Map概览 Java中有四种常见的Map实现,Has ...

  8. Maven基础配置—上传jar包到私服

    一.配置 在需要上传的工程中的pom.xml文件中加入下面的配置 <distributionManagement> <repository> <id>release ...

  9. 在MVC中处理异常的总结

    无论是桌面程序还是web程序,异常处理都是必须的. 一般的处理方式是, 捕获异常,然后记录异常的详细信息到文本文件或者数据库中.在Asp.net MVC中可以使用内建的filter——HandleEr ...

  10. SQL语句查询某表的所有字段及数据类型

    SQL语句查询某表的所有字段及数据类型 SELECT name AS column_name , TYPE_NAME(system_type_id) AS column_type , max_leng ...