在使用时,首先创建一个事件监听器,事件监听器包含以下几种:
- 触摸事件 (EventListenerTouch)
- 键盘响应事件 (EventListenerKeyboard)
- 加速记录事件 (EventListenerAcceleration)
- 鼠标响应事件 (EventListenerMouse)
- 自定义事件 (EventListenerCustom)
以上事件监听器统一由 _eventDispatcher
来进行管理。它的工作需要三部分组成:
- 事件分发器 EventDispatcher
- 事件类型 EventTouch, EventKeyboard 等
- 事件监听器 EventListenerTouch, EventListenerKeyboard 等
触摸事件:
// 创建一个事件监听器 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(0, 0, s.width, s.height);
// 点击范围判断检测
if (rect.containsPoint(locationInNode))
{
log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
target->setOpacity(180);
return true;
}
return false;
};
// 触摸移动时触发
listener1->onTouchMoved = [](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// 移动当前按钮精灵的坐标位置
target->setPosition(target->getPosition() + touch->getDelta());
};
// 点击事件结束处理
listener1->onTouchEnded = [=](Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
log("sprite onTouchesEnded.. ");
target->setOpacity(255);
// 重新设置 ZOrder,显示的前后顺序将会改变
if (target == sprite2)
{
sprite1->setZOrder(100);
}
else if(target == sprite1)
{
sprite1->setZOrder(0);
}
};
添加事件监听器到事件分发器
// 添加监听器
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
键盘处理事件:
// 初始化并绑定 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); }
加速计事件:
在使用加速计事件监听器之前,需要先启用此硬件设备:
Device::setAccelerometerEnabled(true);
然后创建对应的监听器,在创建回调函数时,可以使用 lambda 表达式创建匿名函数,也可以绑定已有的函数逻辑实现,如下:
auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(AccelerometerTest::onAcceleration, this)); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); // 加速计回调函数原型实现 void AccelerometerTest::onAcceleration(Acceleration* acc, Event* event) { // 这里处理逻辑 }
鼠标事件:
在 3.0 中多了鼠标捕获事件派发,这可以在不同的平台上,丰富我们游戏的用户体验。
_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()); // ... }
自定义事件:
以上是系统自带的事件类型,事件由系统内部自动触发,如 触摸屏幕,键盘响应等,除此之外,还提供了一种 自定义事件,简而言之,它不是由系统自动触发,而是人为的干涉,如下:
_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, 1);
以上定义了一个 “自定义事件监听器”,实现了一些逻辑,并且添加到事件分发器。那么以上逻辑是在什么情况下响应呢?请看如下:
static int count = 0; ++count; char* buf = new char[10]; sprintf(buf, "%d", count); EventCustom event("game_custom_event1"); event.setUserData(buf); _eventDispatcher->dispatchEvent(&event); CC_SAFE_DELETE_ARRAY(buf);
定义了一个 EventCustom
,并且设置了其 UserData 数据,手动的通过 _eventDispatcher->dispatchEvent(&event);
将此事件分发出去,从而触发之前所实现的逻辑。
我们可以通过以下方法移除一个已经被添加了的监听器。
_eventDispatcher->removeEventListener(listener);
也可以使用如下方法,移除当前事件分发器中所有监听器。
_eventDispatcher->removeAllEventListeners();
当使用 removeAll
的时候,此节点的所有的监听将被移除,推荐使用 指定删除的方式。
注意:removeAll 之后 菜单 也不能响应。因为它也需要接受触摸事件。