cocos2d-x Programmers Guide v3.3 译本和阅读笔记(第8章:事件派发器)

来源:互联网 发布:照片动态软件下载 编辑:程序博客网 时间:2024/05/16 16:07

Cocos2d-x Programmers Guide v3.3 译本和阅读笔记

原著是英文,本文只是一个个人的简单理解的中文的非正式翻译,供自己学习使用,参考需谨慎。
向原著的作者SlackMoehrle, Ricardo, Justin, Nite , Kai, Minggo, Wenhai, Tony, Yingtao, Rao 致敬。


第八章:事件派发器

什么是事件派发机制

事件派发 是一种响应用户事件的机制。
基本要素:

  • 事件侦听器封装你的事件处理代码
  • 事件派发器通知事件侦听器用户事件
  • 事件对象包含了事件的信息

5种类型的事件侦听器

触摸事件侦听器 ——响应触摸事件
键盘事件侦听器 ——响应键盘事件
加速度事件侦听器 ——响应加速器事件
鼠标事件侦听器 ——响应鼠标事件
自定义事件侦听器 —— 响应自定义事件

固定优先级和场景图形优先级(节点优先级)

事件派发器通过优先级来决定事件先派发个哪一个侦听器
固定优先级 是一个整数。优先级整数小的将比大的更早获得事件,级数值小的优先级高。
场景图形优先级(节点优先级) 是与节点绑定的。场景中的节点z-Order越大(就是绘制在屏幕最上层)的将最先收到事件。这样的机制确保了触摸事件的响应是在屏幕上是“由表及里”的。
还记得第二章,我们用下面这个图讨论场景图形么?
这里写图片描述
如果你记得那太好了,当我们使用节点优先级的时候,实际上就是沿着这颗数到着走 H,I,G,F,E,D,C,B,A.(译者:这个顺序看上去有些令人你混乱,大家可以不必纠结于此,先下读,理解其意即可)。当事件触发的时候,H收到这个事件,并且决定吞噬还是向I传递这个事件,I也会做相同的事,吞噬或者传递给G,以此类推直到事件被吞噬或者不在有可响应的节点。

触摸事件

在移动设备上,触摸时间应该是最重要的事件了。他们很容是创建并且拥有非常丰富的功能。想让我们讲解一下什么是触摸事件吧。当你触摸你的移动设备的时候,它就会响应这个触摸,看上去好像你触摸的位置决定了你触摸了什么东西,你的触摸就就是这样被响应的。当然也有可能你想触摸的东西被其它的什么东西遮挡住,致使你的触摸并没有得到响应。触摸事件通常被分配一个优先级,优先级最高的将会响应这个事件。下面代码展示了如何试用基本触摸事件:

// Create a "one by one" touch event listener// (processes one touch at a time)auto listener1 = EventListenerTouchOneByOne::create();// trigger when you push downlistener1->onTouchBegan = [](Touch* touch, Event* event){    // your code    return true; // if you are consuming it };    // trigger when moving touchlistener1->onTouchMoved = [](Touch* touch, Event* event){    // your code};// trigger when you let uplistener1->onTouchEnded = [=](Touch* touch, Event* event){    // your code};// Add listener_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);

如你所见,当你试用触摸事件的时候,其实是有三个不同的事件在起作用。这三个事件的调用时间也是不同的。
onTouchBegan 是当你按下的时候触发。
onTouchMoved 是当你按住并且移动的时候触发。
onTouchEnded 是抬起手指的时候触发的。

事件吞噬

吞噬事件,就是消耗了这个事件使得它不按照从高优先级到低优先级的规则向其他对象传递。这很容易:

// When "swallow touches" is true, then returning 'true' from the // onTouchBegan method will "swallow" the touch event, preventing // other listeners from using it. listener1->setSwallowTouches(true);// you should also return true in onTouchBegan()listener1->onTouchBegan = [](Touch* touch, Event* event){    // your code    return true; };

创建键盘事件

对于桌面游戏(电脑上的),键盘是非常有用的。Cocos2d-x同样也支持键盘事件。和上面的触摸事件一样,键盘事件也同样非常简单:

// creating a keyboard event listenerauto listener = EventListenerKeyboard::create();listener->onKeyPressed = CC_CALLBACK_2(KeyboardTest::onKeyPressed, this); listener->onKeyReleased = CC_CALLBACK_2(KeyboardTest::onKeyReleased, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);// Implementation of the keyboard event callback function prototypevoid 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);}

创建加速度事件

一些移动设备带有加速度传感器。加速度检测器是一个可以测量重力或者各个方向加速的的传感器。一个简单的例子,你可以来回移动你的手机来改变你手机的加速的。Cocos2d-x也支持这些事件。在创建加速度传感器事件之前。你需要先打开你手机上的传感器。

Device::setAccelerometerEnabled(true);// creating an accelerometer eventauto listener = EventListenerAcceleration::create(CC_CALLBACK_2(AccelerometerTest::onAcceleration, this));_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);// Implementation of the accelerometer callback function prototypevoid AccelerometerTest::onAcceleration(Acceleration* acc, Event* event){    // Processing logic here}

创建鼠标事件

当然Cocos2d-x也支持鼠标事件。

_mouseListener = EventListenerMouse::create()_mouseListener->onMouseMove = CC_CALLBACK_1(MouseTest::onMouseMove, this);_mouseListener->onMouseUp = CC_CALLBACK_1(MouseTest::onMouseUp, this);_mouseListener->onMouseDown = CC_CALLBACK_1(MouseTest::onMouseDown, this);_mouseListener->onMouseScroll = CC_CALLBACK_1(MouseTest::onMouseScroll, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);void MouseTest::onMouseDown(Event *event){    EventMouse* e = (EventMouse*)event; string str = "Mouse Down detected, Key: ";     str += tostr(e->getMouseButton());    // ...}void MouseTest::onMouseUp(Event *event){    EventMouse* e = (EventMouse*)event; string str = "Mouse Up detected, Key: ";     str += tostr(e->getMouseButton());    // ...}void MouseTest::onMouseMove(Event *event){    EventMouse* e = (EventMouse*)event;    string str = "MousePosition X:";    str = str + tostr(e->getCursorX()) + " Y:" + tostr(e->getCursorY());    // ...}void MouseTest::onMouseScroll(Event *event){    EventMouse* e = (EventMouse*)event;    string str = "Mouse Scroll detected, X: ";    str = str + tostr(e->getScrollX()) + " Y: " + tostr(e->getScrollY());     // ...}

注册事件到派发器

注册事件非常容易,以触摸事件为例:

// Add listener_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,sprite1);

有一点非常重要,一个触摸事件只能注册一个对象,如果你希望在多个对象上使用同样的侦听器,那么你需要克隆这个侦听器。

// Add listener_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,sprite1);// Add the same listener to multiple objects._eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);

从事件派发器上移除事件

下面的方法可以移除一个已经添加的事件:

_eventDispatcher->removeEventListener(listener);

尽管看上去不同,但是事实上我们之前讨论的内建节点对象也使用相同的事件派发方式。这很重要,以菜单为例。当你点击菜单中的选项时,你实际上是触发了一个事件。对于内建节点你也可以使用 removeEventListener() 来移除事件。

1 0