摘要: 此文对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有以下几种类型:

    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_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个队列中. 也就是在这样一个字段中:

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. ProgressBar.js – 漂亮的响应式 SVG 进度条

    ProgressBar.js 是一个借助动态 SVG 路径的漂亮的,响应式的进度条效果.使用 ProgressBar.js 可以很容易地创建任意形状的进度条.这个 JavaScript 库提供线条,圆 ...

  2. 总结CSS3新特性(选择器篇)

    CSS3新增了嗯- -21个选择器,脚本通过控制台在这里运行; ~: p ~ p { color : red;/*此条规则将用于p后边所有的p...就是除了第一个p的所有p,规则同p:not(:nth ...

  3. SAP用户权限解剖及自修改

    通常BASIS会使用PFCG做权限管理,时你保存时会产生一个系统外的profile name,记得SU01时用户有profile 和role两栏位吗?它们的关系如何呢? 首先明白几个概念.1.acti ...

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

    Question 16 You are designing a SharePoint 2010 solution to manage statements of work. You need to d ...

  5. 阿里云服务器怎么去掉tomcat的8080端口

    前言:最近在阿里云申请了一个云服务器,然后已买了一个域名.比如www.haha.com ; 在云服务器上安装了tomcat ,访问服务器就成了 http://www.haha.com:8080/ . ...

  6. PHP将uncode转utf8,一行代码解决问题

    在很多场合能看到unicode编码过的文字,如“\u6d3b\u52a8\u63a5\u53e3”,虽然程序会认识,但人眼无法阅读,很不方便,网络上很多人写了很多的转换函数,但是一个比一个臃肿,终于发 ...

  7. yii2 输出xml格式数据

    作者:白狼 出处:http://www.manks.top/yii2_xml_response.html.html本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文 ...

  8. vim添加Vundle插件

    1.git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim 2.vim /etc/vimrc se ...

  9. (1)编写一个接口ShapePara,要求: 接口中的方法: int getArea():获得图形的面积。int getCircumference():获得图形的周长 (2)编写一个圆类Circle,要求:圆类Circle实现接口ShapePara。 该类包含有成员变量: radius:public 修饰的double类型radius,表示圆的半径。 x:private修饰的double型变量x,

    package com.hanqi.test; //创建接口 public interface ShapePara { //获取面积的方法 double getArea(); //获取周长的方法 do ...

  10. MySQL客户端工具 SQLyog

    我最喜欢它的History功能,把执行过的操作对应语句都输出出来,一些麻烦的语句用GUI操作后,还能保存对应的sql语句.不错! 官网:http://www.webyog.com 下面是官方的介绍:S ...