cocos基础教程(11)事件分发机制
cocos3.0的事件分发机制:
- 创建一个事件监听器-用来实现各种触发后的逻辑。
- 事件监听器添加到事件分发器
_eventDispatcher,所有事件监听器有这个分发器统一管理。
事件监听器有以下几种:
- 触摸事件 (EventListenerTouch)
- 键盘响应事件 (EventListenerKeyboard)
- 鼠标响应事件 (EventListenerMouse)
- 自定义事件 (EventListenerCustom)
- 加速记录事件 (EventListenerAcceleration)
_eventDispatcher的工作由三部分组成:
- 事件分发器 EventDispatcher
- 事件类型 EventTouch, EventKeyboard 等
- 事件监听器 EventListenerTouch, EventListenerKeyboard 等
触摸事件
在处理触摸事件时,既可以重写三个方法onTouchBegan,onTouchMoved和onTouchEnded,也可以直接通过Lambda表达式完成响应逻辑。其中的触摸监听类型触摸事件分为EventListenerTouchOneByOne和EventListenerTouchAllAtOnce。EventListenerTouchOneByOne 表示的是单点触摸;而EventListenerTouchAllAtOnce 表示的就是多点触摸。
- 只需创建多点触摸事件监听器。
- 将其添加到事件分发器中即可。
// 创建一个事件监听器类型为 OneByOne 的单点触摸
auto listener1 = EventListenerTouchOneByOne::create();
// 设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞没
listener1->setSwallowTouches(true); // 使用 lambda 实现 onTouchBegan 事件回调函数
listener1->onTouchBegan = [](Touch* touch, Event* event){
// 获取事件所绑定的 target
auto target = static_cast<Sprite*>(event->getCurrentTarget()); // 获取当前点击点所在相对按钮的位置坐标
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();
Rect rect = Rect(, , s.width, s.height); // 点击范围判断检测
if (rect.containsPoint(locationInNode))
{
log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
target->setOpacity();
return true;
}
return false;
}; // 触摸移动时触发
listener1->onTouchMoved = [](Touch* touch, Event* event){...}; // 点击事件结束处理
listener1->onTouchEnded = [=](Touch* touch, Event* event){...};
最后需要将事件监听器添加到事件分发器
// 添加监听器
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
以上代码中_eventDispatcher是Node的属性,通过它管理当前节点(场景、层、精灵等)的所有事件的分发。但它本身是一个单例模式值的引用,在Node的构造函数中,通过Director::getInstance()->getEventDispatcher(); 获取,有了这个属性,就能方便的处理事件。
注意:当再次使用 listener1 的时候,需要使用clone()方法创建一个新的克隆,因为在使用addEventListenerWithSceneGraphPriority或者addEventListenerWithFixedPriority方法时,会对当前使用的事件监听器添加一个已注册的标记,这使得它不能够被添加多次。另外,有一点非常重要,FixedPriority listener添加完之后需要手动remove,而SceneGraphPriority listener是跟Node绑定的,在Node的析构函数中会被移除。具体的示例用法可以参考引擎自带的tests。
我们可以通过以下方法移除一个已经被添加了的监听器。
_eventDispatcher->removeEventListener(listener);
也可以使用如下方法,移除当前事件分发器中所有监听器。
_eventDispatcher->removeAllEventListeners();
当使用removeAll的时候,此节点的所有的监听将被移除,推荐使用 指定删除的方式。removeAll之后菜单也不能响应。因为它也需要接受触摸事件。
键盘响应事件
键盘响应事件和处理触摸事件使用了相同的处理方式,一下代码演示如何处理键盘响应事件:
// 初始化并绑定
auto listener = EventListenerKeyboard::create();
listener->onKeyPressed = CC_CALLBACK_2(KeyboardTest::onKeyPressed, this);
listener->onKeyReleased = CC_CALLBACK_2(KeyboardTest::onKeyReleased, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); // 键位响应函数原型
void KeyboardTest::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event)
{
log("Key with keycode %d pressed", keyCode);
} void KeyboardTest::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event)
{
log("Key with keycode %d released", keyCode);
}
鼠标响应事件
在 3.0 中多了鼠标捕获事件派发,这可以在不同的平台上,丰富我们游戏的用户体验。
下面代码实现鼠标响应事件的实现步骤:
// 创建监听器
_mouseListener = EventListenerMouse::create(); // 时间响应逻辑
_mouseListener->onMouseMove = [=](Event *event){
EventMouse* e = (EventMouse*)event;
string str = "Mouse Down detected, Key: ";
str += tostr(e->getMouseButton());
// ...
};
_mouseListener->onMouseUp = [=](Event *event){...};
_mouseListener->onMouseDown = [=](Event *event){...};
_mouseListener->onMouseScroll = [=](Event *event){...};
// 添加到事件分发器
_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);
自定义事件
以上是系统自带的事件类型,事件由系统内部自动触发,如 触摸屏幕,键盘响应等,除此之外,还提供了一种 自定义事件,简而言之,它不是由系统自动触发,而是人为的干涉,如下:
_listener = EventListenerCustom::create("game_custom_event1", [=](EventCustom* event){
std::string str("Custom event 1 received, ");
char* buf = static_cast<char*>(event->getUserData());
str += buf;
str += " times";
statusLabel->setString(str.c_str());
});
_eventDispatcher->addEventListenerWithFixedPriority(_listener, );
以上定义了一个 “自定义事件监听器”,实现了相关逻辑,并且添加到事件分发器。上面的自定义事件将由以下代码触发:
static int count = ;
++count;
char* buf = new char[];
sprintf(buf, "%d", count);
EventCustom event("game_custom_event1");
event.setUserData(buf);
if(...)
{
_eventDispatcher->dispatchEvent(&event);
}
CC_SAFE_DELETE_ARRAY(buf);
定义一个 EventCustom,并且设置了其 UserData 数据,手动的通过 _eventDispatcher->dispatchEvent(&event); 将此事件分发出去,从而触发之前所实现的逻辑。
加速计事件
除了触摸,移动设备上一个很重要的输入源是设备的方向,因此大多数设备都配备了加速计,用于测量设备静止或匀速运动时所受到的重力方向。
重力感应来自移动设备的加速计,通常支持X,Y和Z三个方向的加速度感应,所以又称为三向加速计。在实际应用中,可以根据3个方向的力度大小来计算手机倾斜的角度或方向。
3.0中,新的事件机制下,我们需要通过创建一个加速计监听器EventListenerAcceleration,其静态create方法中有个Acceleration的参数需要注意。Acceleration是一个类,包含了加速计获得的3个方向的加速度,相关代码如下:
class Acceleration
{
public:
double x;
double y;
double z; double timestamp; Acceleration(): x(), y(), z(), timestamp() {}
};
该类中每个方向的加速度大小都为一个重力加速度大小。
在使用加速计事件监听器之前,需要先启用此硬件设备:
Device::setAccelerometerEnabled(true);
然后创建对应的监听器,在创建回调函数时,可以使用 lambda 表达式创建匿名函数,也可以绑定已有的函数逻辑实现,如下:
auto listener = EventListenerAcceleration::create([=](Acceleration* acc, Event* event){
//逻辑代码段
});
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
cocos基础教程(11)事件分发机制的更多相关文章
- Android查缺补漏(View篇)--事件分发机制
事件分发机制是Android中非常重要的一个知识点,同时也是难点,相信到目前为止很多Android开发者对事件分发机制并没有一个非常系统的认识,当然也包括博主个人在内.可能在平时的开发工作中我们并没有 ...
- 浅谈Android View事件分发机制
引言 前面的文章介绍了View的基础知识和View的滑动,今天我们来介绍View的另一个核心知识,View的事件分发机制. 点击事件的传递规则 所谓的点击事件的分发机制,其实就是对MotionEven ...
- 高级UI晋升之触摸事件分发机制(一)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 0. 前言 鉴于安卓分发机制较为复杂,故分为多个层次进行讲解,分别为基础篇.实践 ...
- Android中的事件分发机制总结
Android 的事件分发机制 一.View的事件分发总结: View的onTouchEvent和OnTouch区别 还是以自定义的TestButton为例. 我们可以通过重写onTouchEven ...
- Android事件分发机制详解
事件分发机制详解 一.基础知识介绍 1.经常用的事件有:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP等 2 ...
- Android与javascript中事件分发机制的简单比较
在前面两篇博客中,我们讨论了Android中的事件分发的相关内容,那么在本篇博客当中,我们就简单探讨一下html或javascript中的事件分发机制,并进行简单的对比. 在前端中,对事件进行绑定有三 ...
- Android的Touch事件分发机制简单探析
前言 Android中关于触摸事件的分发传递是一个很值得研究的东西.曾不见你引入了一个ListView的滑动功能,ListView就不听你手指的指唤来滚动了:也不知道为啥Button设置了onClic ...
- cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析
(一) Android平台下: cocos2dx 版本3.2,先导入一个android工程,然后看下AndroidManifest.xml <application android:label= ...
- Cocos2d-X研究之v3.x 事件分发机制具体解释
事件分发机制 " src="http://www.cgzhw.com/wp-content/uploads/2014/07/inherent3.png" style=&q ...
随机推荐
- Stream 流操作
Stream 类 先看下面的图 Stream 是所有流的抽象基类(不能被实例化,需要使用他的派生类FileStream/MemoryStream/BufferedStream).流是字节序列的抽象概 ...
- WP8.1&Win10幸运大转盘源码分享
先AD一下我的群:Win10开发者群:53078485 最近在写一个APP,其中需要一个转盘动画的源码,找了很多但是都没有找到,无奈只好自己来写,写完效果自己还是比较满意的,分享出来,有需要的童鞋可以 ...
- FlipView For Xamarin.Form 之 IOS
之前写过两篇博文 是关于 Android 和 Windows Phone 下的 FlipView 的实现. 上上周,有个印度佬通过 GitHub 找到我, 问我有没有打算个 ios 端的,还说比较了相 ...
- WCF入门 (13)
前言 公司略无聊,周三前同事推荐跳槽,于是会去更新了一下简历,突然发现,快一年了,我竟然想不出我可以往简历上添加点什么值得自豪的东西.下午和小伙伴聊了一会天,他告诉我,可以往简历上写上“英语口语水平有 ...
- Symfony学习--目录和入口
1 目录结构 根目录下有: app src vendor web app是存放应用的一些配置文件,如果有一些配置文件或者文档,应当存放在这里面. src是存放你的项目的php代码,这里的php至少必须 ...
- 四则运算 Day3
总结篇 一开始看到自己的成绩是接近及格线的时候,我的内心是崩溃的,就差辣么一点点..但是感谢老师给了这么一个补交作业的机会.在参考博客园相关四则运算题目后,做了一个适用小学一二年级使用的简单的四则运算 ...
- OC基础--关键字@property 和 @synthesize
一.@property关键字需要掌握的知识: 1.用在@interface中,用来自动生成setter和getter的声明 例:@property int age;--相当于执行了右边的代码--> ...
- [Asp.net mvc] Asp.net mvc Kendo UI Grid的使用(四)
有段时间没写博客了,工作状态比较忙,抽空继续总结下Grid的使用,这次主要介绍模板以及其他官网介绍不详尽的使用方法.先Show出数据,然后讲解下.后台代码: public ActionResult O ...
- Linux operation strucutre
Under the /usr/src directory. 1.arch目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CP ...
- MVC的URL路由规则
MVC的URL路由规则 Routing的作用:它首先是获取到View传过来的请求,并解析Url请求中Controller和Action以及数据,其次他将识别出来的数据传递给Controller的Act ...