在2.x中处理事件需要用到委托代理(delegate),相信学过2.x的触摸事件的同学,都知道创建和移除的流程十分繁琐。而在3.x中由于加入了C++11的特性,而对事件的分发机制通过事件分发器EventDispatcher 来进行统一的管理。
事件监听器主要有:
  • 触摸事件     : EventListenerTouchOneByOne、EventListenerTouchAllAtOnce
  • 鼠标响应事件 : EventListenerMouse
  • 键盘响应事件 : EventListenerKeyboard
  • 加速计事件   : EventListenerAcceleration
  • 自定义事件   : EventListenerCustom
  • 物理碰撞事件 : EventListenerPhysicsContact
  • 游戏手柄事件 : EventListenerController
【事件分发器】
事件分发器EventDispatcher,用于统一管理事件监听器的所有事件的分发。
1、_eventDispatcher
_eventDispatcher是Node的属性,通过Director::getInstance()->getEventDispatcher() 获得。
_eventDispatcher的工作由三部分组成:
(1)事件分发器 :EventDispatcher。
(2)事件类型   :EventTouch, EventKeyboard 等。
(3)事件监听器 :EventListenerTouch, EventListenerKeyboard 等。
监听器实现了各种触发后的逻辑,在适当时候由事件分发器分发事件类型,然后调用相应类型的监听器。
2、添加/删除监听器
添加监听器:addEventListenerWithSceneGraphPriority,addEventListenerWithFixedPriority。
删除监听器:removeEventListener,removeAllEventListeners。
3、主要函数
包含监听器的添加、删除、暂停、恢复,优先级的设置,手动分发事件等。

// class EventDispatcher : public Ref {

/** * 添加监听器

*  - addEventListenerWithSceneGraphPriority

*  - addEventListenerWithFixedPriority

*  - addCustomEventListener

*/    

//使用 场景图的优先级 为指定事件添加一个监听.     

//listener : 指定要监听的事件.    

//node     : 这个节点的绘制顺序是基于监听优先级.     

//优先级   : 0    

void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);       

//使用 一定的优先级 为指定事件添加一个监听.     

//listener      : 指定要监听的事件.     

//fixedPriority : 这个监听器的固定优先级.    

//优先级        : fixedPriority。(但是不能为0,因为他是场景图的基本优先级)    

void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);       

//用户自定义监听器    

EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function& callback);      

/**

* 删除监听器

*     - removeEventListener

*     - removeEventListenersForType

*     - removeEventListenersForTarget

*     - removeCustomEventListeners

*     - removeAllEventListeners

*/    

//删除指定监听器    

void removeEventListener(EventListener* listener);       

//删除某类型对应的所有监听器    

//EventListener::Type::    

//  单点触摸 : TOUCH_ONE_BY_ONE    

//  多点触摸 : TOUCH_ALL_AT_ONCE    

//  键盘     : KEYBOARD    

//  鼠标     : MOUSE    

//  加速计   : ACCELERATION    

//  自定义   : CUSTOM    

void removeEventListenersForType(EventListener::Type listenerType);       

//删除绑定在节点target上的所有监听器    

void removeEventListenersForTarget(Node* target, bool recursive = false);       

//删除名字为customEventName的所有自定义监听器    

void removeCustomEventListeners(const std::string& customEventName);       

//移除所有监听器     void removeAllEventListeners();      

/**

* 暂停、恢复在节点target上的所有监听器

*     - pauseEventListenersForTarget

*     - resumeEventListenersForTarget

*/    

void pauseEventListenersForTarget(Node* target, bool recursive = false);    

void resumeEventListenersForTarget(Node* target, bool recursive = false);      

/**

* 其他

*     - setPriority

*     - setEnabled

*     - dispatchEvent

*     - dispatchCustomEvent

*/    

//设置某监听器的优先级  

void setPriority(EventListener* listener, int fixedPriority);       

//启用事件分发器    

void setEnabled(bool isEnabled);    

bool isEnabled() const;       

//手动派发自定义事件    

void dispatchEvent(Event* event);       

//给名字为eventName的自定义监听器, 绑定用户数据    

void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr); } //

4、关于事件监听器的优先权
通过 addEventListenerWithSceneGraphPriority 添加的监听器,优先权为0。
通过 addEventListenerWithFixedPriority 添加的监听器,可以自定义优先权,但不能为0。
  • 优先级越低,越先响应事件。
  • 如果优先级相同,则上层的(z轴)先接收触摸事件。
5、使用步骤
(1)获取事件分发器  :dispatcher = Director::getInstance()->getEventDispatcher();
(2)创建监听器      :auto listener = EventListenerTouchOneByOne::create();
(3)绑定响应事件函数:listener->onTouchBegan = CC_CALLBACK_2(callback, this);
(4)将监听器添加到事件分发器dispatcher中:dispatcher->addEventListenerWithSceneGraphPriority(Listener, this);
(5)编写回调响应函数:bool callback(Touch* touch, Event* event) { ... }
【触摸事件】
1、单点触摸:EventListenerTouchOneByOne
单点触摸监听器相关:

//       

static EventListenerTouchOneByOne* create();

std::function onTouchBegan; //只有这个返回值为 bool    

std::function onTouchMoved;    

std::function onTouchEnded;    

std::function onTouchCancelled;

//

使用举例:

//    

//获取事件分发器    

auto dispatcher = Director::getInstance()->getEventDispatcher();       

//创建单点触摸监听器 EventListenerTouchOneByOne    

auto touchListener = EventListenerTouchOneByOne::create();           

//单点触摸响应事件绑定    

touchListener->onTouchBegan     = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);    

touchListener->onTouchMoved     = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);    

touchListener->onTouchEnded     = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);    

touchListener->onTouchCancelled = CC_CALLBACK_2(HelloWorld::onTouchCancelled, this);           

//在事件分发器中,添加触摸监听器,事件响应委托给 this 处理    

dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);          

//单点触摸事件响应函数    

bool onTouchBegan(Touch *touch, Event *unused_event)     { CCLOG("began"); return true; }    

void onTouchMoved(Touch *touch, Event *unused_event)     { CCLOG("moved"); }    

void onTouchEnded(Touch *touch, Event *unused_event)     { CCLOG("ended"); }    

void onTouchCancelled(Touch *touch, Event *unused_event) { CCLOG("cancelled"); } //

2、多点触摸:EventListenerTouchAllAtOnce
多点触摸监听器相关:

//    

static EventListenerTouchAllAtOnce* create();           

std::function<void(const std::vector&, Event*)> onTouchesBegan;    

std::function<void(const std::vector&, Event*)> onTouchesMoved;    

std::function<void(const std::vector&, Event*)> onTouchesEnded;    

std::function<void(const std::vector&, Event*)> onTouchesCancelled;

//


使用举例:

//     //获取事件分发器    

auto dispatcher = Director::getInstance()->getEventDispatcher();           

//创建多点触摸监听器 EventListenerTouchAllAtOnce    

auto touchesListener = EventListenerTouchAllAtOnce::create();           

//多点触摸响应事件绑定    

touchesListener->onTouchesBegan     = CC_CALLBACK_2(HelloWorld::onTouchesBegan, this);    

touchesListener->onTouchesMoved     = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this);    

touchesListener->onTouchesEnded     = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this);    

touchesListener->onTouchesCancelled = CC_CALLBACK_2(HelloWorld::onTouchesCancelled, this);           

//在事件分发器中,添加触摸监听器,事件响应委托给 this 处理    

dispatcher->addEventListenerWithSceneGraphPriority(touchesListener, this);          

//多点触摸事件响应函数    

void onTouchesBegan(const std::vector& touches, Event *unused_event)    { CCLOG("began"); }    

void onTouchesMoved(const std::vector& touches, Event *unused_event)    { CCLOG("moved"); }    

void onTouchesEnded(const std::vector& touches, Event *unused_event)    { CCLOG("ended"); }    

void onTouchesCancelled(const std::vector&touches, Event *unused_event) { CCLOG("cancelled"); } //

【鼠标事件】
EventListenerMouse,主要用于监听鼠标的点击、松开、移动、滚轮的事件。
鼠标事件监听器相关:

//    

static EventListenerMouse* create();       

std::function onMouseDown;      //按下鼠标, 单击鼠标    

std::function onMouseUp;       //松开鼠标, 按下的状态下松开    

std::function onMouseMove;      //移动鼠标, 在屏幕中移动    

std::function onMouseScroll;    //滚动鼠标, 滚动鼠标的滚轮

//


使用举例:

//     //获取事件分发器    

auto dispatcher = Director::getInstance()->getEventDispatcher();           

//创建鼠标事件监听器 EventListenerMouse    

EventListenerMouse* mouseListenter = EventListenerMouse::create();           

//鼠标事件响应函数    

mouseListenter->onMouseDown   = CC_CALLBACK_1(HelloWorld::onMouseDown,   this);    

mouseListenter->onMouseUp     = CC_CALLBACK_1(HelloWorld::onMouseUp,     this);    

mouseListenter->onMouseMove   = CC_CALLBACK_1(HelloWorld::onMouseMove,   this);    

mouseListenter->onMouseScroll = CC_CALLBACK_1(HelloWorld::onMouseScroll, this);           

//添加鼠标事件监听器,事件响应处理委托给this    

dispatcher->addEventListenerWithSceneGraphPriority(mouseListenter, this);                  

//事件响应函数    

void onMouseDown(Event* event)   { CCLOG("Down"); }    

void onMouseUp(Event* event)     { CCLOG("UP"); }    

void onMouseMove(Event* event)   { CCLOG("MOVE"); }    

void onMouseScroll(Event* event) { CCLOG("Scroll"); }

//

【键盘事件】
EventListenerKeyboard,主要用于监听键盘某个键的按下、松开的事件。
键盘事件监听器相关:

//    

static EventListenerKeyboard* create();       

std::function onKeyPressed;  //按下某键    

std::function onKeyReleased; //松开某键              

//键盘按键枚举类型 EventKeyboard::KeyCode    

//KeyCode的值对应的不是键盘的键值、也不是ASCII码,只是纯粹的枚举类型      

//如:    

//  EventKeyboard::KeyCode::KEY_A    

//  EventKeyboard::KeyCode::KEY_1    

//  EventKeyboard::KeyCode::KEY_F1    

//  EventKeyboard::KeyCode::KEY_SPACE    

//  EventKeyboard::KeyCode::KEY_ALT    

//  EventKeyboard::KeyCode::KEY_SHIFT

//


使用举例:

//     //获取事件分发器    

auto dispatcher = Director::getInstance()->getEventDispatcher();       

//创建键盘按键事件监听器    

EventListenerKeyboard* keyboardListener = EventListenerKeyboard::create();           

//绑定事件响应函数    

keyboardListener->onKeyPressed = CC_CALLBACK_2(HelloWorld::onKeyPressed, this);    

keyboardListener->onKeyReleased = CC_CALLBACK_2(HelloWorld::onKeyReleased, this);           

//添加监听器    

dispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);                  

//事件响应函数    

void onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event) {         

  if (EventKeyboard::KeyCode::KEY_J == keyCode) {             

    CCLOG("Pressed: J");         

  }    

}    

void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event) {         

  if (EventKeyboard::KeyCode::KEY_SPACE == keyCode) {             

    CCLOG("Released: SPACE");         

  }    

}

//

【加速计事件】
EventListenerAcceleration,主要用于监听移动设备的所受重力方向感应事件。
重力感应来自移动设备的加速计,通常支持 (X, Y, Z) 三个方向的加速度感应,所以又称为三向加速计。在实际应用中,可以根据3个方向的力度大小来计算手机倾斜的角度或方向。
1、加速计信息类Acceleration
该类中每个方向的加速度,大小都为一个重力加速度大小。

//加速计信息     class Acceleration     {         double x; double y; double z;     }; //

2、开启加速计感应
在使用加速计事件监听器之前,需要先启用此硬件设备:
Device::setAccelerometerEnabled(true);
 
3、加速计监听器相关

//    

static EventListenerAcceleration* create(const std::function& callback);       

std::function onAccelerationEvent;

//


4、使用举例

//     //标签: 显示加速计信息    

label = Label::createWithTTF("no used", "Marker Felt.ttf", 12);    

label->setPosition(visibleSize / 2);    

this->addChild(label);              

//小球: 可视化加速计    

ball = Sprite::create("ball.png");    

ball->setPosition(visibleSize / 2);    

this->addChild(ball);          

//获取事件分发器    

auto dispatcher = Director::getInstance()->getEventDispatcher();       

//需要开启移动设备的加速计    

Device::setAccelerometerEnabled(true);           

//创建加速计事件监听器    

auto accelerationListener = EventListenerAcceleration::create(CC_CALLBACK_2(HelloWorld::onAccelerationEvent, this));           

//添加加速计监听器    

dispatcher->addEventListenerWithSceneGraphPriority(accelerationListener, this);                  

//事件响应函数    

void HelloWorld::onAccelerationEvent(Acceleration* acceleration, Event* event)     {

        char s[100];         

    sprintf(s, "X: %f; Y: %f; Z:%f; ", acceleration->x, acceleration->y, acceleration->z);         

    label->setString(s);            //改变小球ball的位置         

    float x = ball->getPositionX() + acceleration->x * 10;         

    float y = ball->getPositionY() + acceleration->y * 10;         

    Vec2 pos = Vec2(x, y);         

    pos.clamp(ball->getContentSize() / 2, Vec2(288, 512) - ball->getContentSize() / 2);         

    ball->setPosition(pos); //设置位置    

}

//

5、实际效果
在电脑上看不出效果,需要移植到手机上,才能看到加速计的效果。
【自定义事件】
以上是系统自带的事件类型,事件由系统内部自动触发,如 触摸屏幕,键盘响应等。
EventListenerCustom 自定义事件,它不是由系统自动触发,而是人为的干涉。
1、创建自定义监听器

//    

//eventName : 监听器名字    

//callback  : 监听器函数    

static EventListenerCustom* create(const std::string& eventName, const std::function& callback);

//

2、分发自定义事件
自定义的事件监听器,需要通过手动的方式,将事件分发出去。
通过 EventCustom(string eventName);     来获取自定义监听器。
通过 dispatcher->dispatchEvent(&event); 来手动将事件分发出去。

//    

EventCustom event("your_event_type");    

dispatcher->dispatchEvent(&event);

//


3、使用举例

//    

//获取事件分发器    

auto dispatcher = Director::getInstance()->getEventDispatcher();       

//创建自定义事件监听器    

//监听器名字  : "custom_event"    

//事件响应函数: HelloWorld::onCustomEvent    

auto customListener = EventListenerCustom::create("custom_event", CC_CALLBACK_1(HelloWorld::onCustomEvent, this));           

//添加自定义事件监听器,优先权为1    

dispatcher->addEventListenerWithFixedPriority(customListener, 1);       

//手动分发监听器的事件,通过dispatchEvent    

EventCustom event = EventCustom("custom_event");    

dispatcher->dispatchEvent(&event); 

//

事件响应函数    

void HelloWorld::onCustomEvent(EventCustom* event)     {

        CCLOG("onCustomEvent");    

  }

//

4、说明
  • 每个自定义的事件监听器,都有一个监听器名字eventName。
  • 需要手动通过 dispatcher->dispatchEvent(&event); 来手动将事件分发出去。
  • 可以通过 dispatcher->dispatchCustomEvent(,); 来给自定义事件监听器绑定一个用户数据。

Cocos2d-x 3.x事件分发机制总结的更多相关文章

  1. Cocos2d-x 3.2 学习笔记(九)EventDispatcher事件分发机制

    EventDispatcher事件分发机制先创建事件,注册到事件管理中心_eventDispatcher,通过发布事件得到响应进行回调,完成事件流. 有五种不同的事件机制:EventListenerT ...

  2. cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析

    (一) Android平台下: cocos2dx 版本3.2,先导入一个android工程,然后看下AndroidManifest.xml <application android:label= ...

  3. Cocos2d-X研究之v3.x 事件分发机制具体解释

    事件分发机制 " src="http://www.cgzhw.com/wp-content/uploads/2014/07/inherent3.png" style=&q ...

  4. Android事件分发机制浅谈(一)

    ---恢复内容开始--- 一.是什么 我们首先要了解什么是事件分发,通俗的讲就是,当一个触摸事件发生的时候,从一个窗口到一个视图,再到一个视图,直至被消费的过程. 二.做什么 在深入学习android ...

  5. Android事件分发机制浅谈(二)--源码分析(ViewGroup篇)

    上节我们大致了解了事件分发机制的内容,大概流程,这一节来分析下事件分发的源代码. 我们先来分析ViewGroup中dispatchTouchEvent()中的源码 public boolean dis ...

  6. Atitit View事件分发机制

    1. Atitit View事件分发机制 1. Atitit View事件分发机制1 1.1. 三个关键方法 dispatchTouchEvent onInterceptTouchEvent onTo ...

  7. Android Touch事件分发机制学习

    Android  事件分发机制 ViewGroup dispatchTouchEvent 返回true dispatchTouchEvent: Activity ACTION_DOWN Myrelat ...

  8. android 事件分发机制

    1.View的事件分发机制 一个button,简单一点就是onTouch,还有onclick事件,我们一个一个来分析 首先响应的是dispatchTouchEvent public boolean d ...

  9. Android View 事件分发机制 源码解析 (上)

    一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...

  10. Android中View的事件分发机制

    简介 事件也称MotionEvent,事件分发机制就是对MotionEvent事件的分发过程,即当一个MotionEvent发生之后,系统需要把这个事件传递给一个具体的View. 点击事件的分发过程由 ...

随机推荐

  1. How to write own add-in for SSMS 2012 (Final release version)

    原文 How to write own add-in for SSMS 2012 (Final release version) Reading internet forums I have noti ...

  2. 并行编程之PLINQ

    并行编程之PLINQ 并行 LINQ (PLINQ) 是 LINQ 模式的并行实现.PLINQ 的主要用途是通过在多核计算机上以并行方式执行查询委托来加快 LINQ to Objects 查询的执行速 ...

  3. WCF、Web API、WCF REST、Web Service 区别

    Web Service It is based on SOAP and return data in XML form. It support only HTTP protocol. It is no ...

  4. NUint使用详解及Visual Studio配置

    NUint使用详解及Visual Studio配置 阅读目录 什么是单元测试? 为什么使用单元测试? NUint使用详解: 示例 属性 断言 简单测试 VS配置: External Tools Vis ...

  5. 线程池python

    原创博文,转载请注明出处 今天在学习python进程与线程时,无意间发现了线程池threadpool模块,见官方文档. 模块使用非常简单,前提是得需要熟悉线程池的工作原理. 我们知道系统处理任务时,需 ...

  6. 【C基础】const用法

    1.const 和 define 异同 同:const 和 define都是修饰常量 异:const修饰的常量只是编译器的一种优化,它是可以通过内存地址修改const修饰的常量:而define修饰的常 ...

  7. MSSQL数据库迁移到Oracle

    MSSQL数据库迁移到Oracle 最近要把一个MSSQL数据库迁移到Oracle上面,打算借助PowerDesigner这个软件来实现;今天简单研究一下这个软件的运用;把一步简单的操作步骤记录下来: ...

  8. Leetcode: UniquePath II

    Description: Follow up for "Unique Paths": Now consider if some obstacles are added to the ...

  9. 基于 WebSocket 构建跨浏览器的实时应用

    Socket.IO – 基于 WebSocket 构建跨浏览器的实时应用 Socket.IO 是一个功能非常强大的框架,能够帮助你构建基于 WebSocket 的跨浏览器的实时应用.支持主流浏览器,多 ...

  10. C#中字符转换问题详解

    C# 出来也有些日子了,最近由于编程的需要,对 C# 的类型转换做了一些研究,其内容涉及 C# 的装箱/拆箱/别名.数值类型间相互转换.字符的 ASCII 码和 Unicode 码.数值字符串和数值之 ...