Cocos2d-x 3.2 EventDispatcher事件分发机制

本文转载于Cocos2d-x v3.2学习笔记中的(九)事件分发机制(EventDispatcher)

EventDispatcher事件分发机制先创建事件,注册到事件管理中心_eventDispatcher,通过发布事件得到响应进行回调,完成事件流。

有五种不同的事件机制:

  • EventListenerTouch 响应触控事件

  • EventListenerKeyboard 响应键盘事件

  • EventListenerAcceleration 响应加速器事件

  • EventListenMouse 响应鼠标事件

  • EventListenerCustom 响应自定义的事件

优先权:

1.优先级越低,越先响应事件

2.如果优先级相同,则上层的(z轴)先接收触摸事件。

事件监听器的优先级:

1.addEventListenerWithSceneGraphPriority 的事件监听器优先级是0,而且在 addEventListenerWithFixedPriority 中的事件监听器的优先级不可以设置为 0,因为这个是保留给 SceneGraphPriority 使用的。

2.另外,有一点非常重要,FixedPriority listener添加完之后需要手动remove,而SceneGraphPriority listener是跟node绑定的,在node的析构函数中会被移除。移除方 法:dispatcher->removeEventListener(listener);

事件管理单例获取:

_eventDispatcher 是Node的属性,通过它管理当前节点(场景、层、精灵等)的所有事件的分发。但它本身是一个单例模式值的引用,在Node的构造函数中,通过 Director::getInstance()->getEventDispatcher(); 获取,有了这个属性,就能方便的处理事件。

触摸事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void EventDispatcherTest::funEventTouch(Sprite* sprite)
{
    this->_eventDispatcher->removeAllEventListeners();
     
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(EventDispatcherTest::onTouchBeganss,this);
    listener->onTouchMoved = CC_CALLBACK_2(EventDispatcherTest::onTouchMovedss,this);
    listener->onTouchEnded = CC_CALLBACK_2(EventDispatcherTest::onTouchEndedss,this);
    listener->onTouchCancelled = CC_CALLBACK_2(EventDispatcherTest::onTouchCancelledss,this);
    listener->setSwallowTouches(true);//是否向下传递
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,sprite);
}
 
bool EventDispatcherTest::onTouchBeganss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
 
    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());
    Size s = target->getContentSize();
    Rect rect = Rect(0, 0, s.width, s.height);
  //判断触摸区域是否在目标上
    if (rect.containsPoint(locationInNode))
    {
        label->setString("onTouchBegan......");
        target->setOpacity(180);
        return true;
    }
    return false;
}
void EventDispatcherTest::onTouchMovedss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
    target->setPosition(target->getPosition() + touch->getDelta());
    label->setString("onTouchMoved......");
}
void EventDispatcherTest::onTouchEndedss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
    target->setOpacity(255);
    label->setString("onTouchEnded......");
}
void EventDispatcherTest::onTouchCancelledss(Touch* touch,Event* ev)
{
    label->setString("onTouchCancelled......");
}

键盘事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void EventDispatcherTest::funEventKeyboard()
{
    this->_eventDispatcher->removeAllEventListeners();
 
    auto listener = EventListenerKeyboard::create();
    listener->onKeyPressed = CC_CALLBACK_2(EventDispatcherTest::onKeyPressedss,this);
    listener->onKeyReleased = CC_CALLBACK_2(EventDispatcherTest::onKeyReleasedss,this);
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}
 
void EventDispatcherTest::onKeyPressedss(EventKeyboard::KeyCode keycode,Event* ev)
{
    char txt[100] = {};
    sprintf_s(txt,"key %d is Pressed!",(int)keycode);
    label->setString(txt);
}
 
void EventDispatcherTest::onKeyReleasedss(EventKeyboard::KeyCode keycode,Event* ev)
{
    label->setString("key is Released!");
}

鼠标事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void EventDispatcherTest::funEventMouse(Sprite* sprite)
{
    this->_eventDispatcher->removeAllEventListeners();
 
    auto listener = EventListenerMouse::create();
    listener->onMouseDown = CC_CALLBACK_1(EventDispatcherTest::onMouseDownss,this);
    listener->onMouseMove = CC_CALLBACK_1(EventDispatcherTest::onMouseMovess,this);
    listener->onMouseUp = CC_CALLBACK_1(EventDispatcherTest::onMouseUpss,this);
    listener->onMouseScroll = CC_CALLBACK_1(EventDispatcherTest::onMouseScrollss,this);
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,sprite);
}
 
void EventDispatcherTest::onMouseDownss(Event* ev)
{
    label->setString("onMouseDown!");
}
void EventDispatcherTest::onMouseMovess(Event* ev)
{
    label->setString("onMouseMove!");
}
void EventDispatcherTest::onMouseUpss(Event* ev)
{
    label->setString("onMouseUp!");
}
void EventDispatcherTest::onMouseScrollss(Event* ev)
{
    label->setString("onMouseScroll!");
}

自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//自定義事件
funEventCustom();
 
//2秒後派發一次自定義事件,測試
scheduleOnce(schedule_selector(EventDispatcherTest::dispatcherCustomEvents),2.0f);
 
void EventDispatcherTest::funEventCustom()
{
    auto listener = EventListenerCustom::create("custom_event_1",CC_CALLBACK_1(EventDispatcherTest::onEventCustom,this));
    this->_eventDispatcher->addEventListenerWithFixedPriority(listener,1);//添加到事件分發器
}
 
void EventDispatcherTest::dispatcherCustomEvents(float at)
{
    //派發事件custom_event_1  事件內容為字符串custom event test!
    this->_eventDispatcher->dispatchCustomEvent("custom_event_1","custom event test!");
}
 
void EventDispatcherTest::onEventCustom(EventCustom* event)
{
    auto data = static_cast<char*>(event->getUserData());
    label->setString(data);
}

加速器事件

除了触摸,移动设备上一个很重要的输入源是设备的方向,因此大多数设备都配备了加速计,用于测量设备静止或匀速运动时所受到的重力方向。

重力感应来自移动设备的加速计,通常支持X,Y和Z三个方向的加速度感应,所以又称为三向加速计。在实际应用中,可以根据3个方向的力度大小来计算手机倾斜的角度或方向。

加速计监听器EventListenerAcceleration,其静态create方法中有个Acceleration的参数。Acceleration是一个类,包含了加速计获得的3个方向的加速度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void EventDispatcherTest::funEventAcceleration()
{
    //啟動硬件設備
    Device::setAccelerometerEnabled(true); 
 
    auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(EventDispatcherTest::onAcceleration,this));
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}
 
void EventDispatcherTest::onAcceleration(Acceleration* acc,Event* event)
{
    char str[100]={};
    sprintf_s(str,"x:%2d,y:%2d,z:%2d,timestamp:%2d",acc->x,acc->y,acc->z,acc->timestamp);
    log(str);
}

示例代码

EventDispatcherTest.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef __EventDispatcherTest__
#define __EventDispatcherTest__
 
#include "cocos2d.h"
 
USING_NS_CC;
 
class EventDispatcherTest : public Layer
{
public:
    CREATE_FUNC(EventDispatcherTest);
    virtual bool init();
    static Scene* createScene();
    LabelTTF* label;
    void funEventTouch(Sprite* sprite);
    void funEventKeyboard();
    void funEventMouse(Sprite* sprite);
    void funEventCustom();
    void funEventAcceleration();
 
    bool onTouchBeganss(Touch* touch,Event* ev);
    void onTouchMovedss(Touch* touch,Event* ev);
    void onTouchEndedss(Touch* touch,Event* ev);
    void onTouchCancelledss(Touch* touch,Event* ev);
 
    void onKeyPressedss(EventKeyboard::KeyCode keycode,Event* ev);
    void onKeyReleasedss(EventKeyboard::KeyCode keycode,Event* ev);
 
    void onMouseDownss(Event* ev);
    void onMouseMovess(Event* ev);
    void onMouseUpss(Event* ev);
    void onMouseScrollss(Event* ev);
 
    void dispatcherCustomEvents(float at);
    void onEventCustom(EventCustom* event);
 
 
    void onAcceleration(Acceleration* acc,Event* event);
};
 
#endif
 
EventDispatcherTest.h

EventDispatcherTest.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include "EventDispatcherTest.h"
Scene* EventDispatcherTest::createScene()
{
    auto scene = Scene::create();
    auto layer = EventDispatcherTest::create();
    scene->addChild(layer);
    return scene;
}
 
bool EventDispatcherTest::init()
{
 
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    label = LabelTTF::create("Hello World""Arial", 24);
    label->setPosition(Vec2(origin.x + visibleSize.width/2,
        origin.y + visibleSize.height - label->getContentSize().height));
    this->addChild(label, 100);
 
    auto sprite = Sprite::create("MagentaSquare.png",Rect(0,0,100,100));
    sprite->setPosition(visibleSize/2);
    this->addChild(sprite);
 
    //funEventTouch(sprite); //觸摸事件
    //funEventKeyboard();    //鍵盤事件
    //funEventMouse(sprite);//鼠標事件
    //funEventAcceleration();//加速器事件
 
    //自定義事件
     funEventCustom();
     //2秒後派發一次自定義事件,測試
     scheduleOnce(schedule_selector(EventDispatcherTest::dispatcherCustomEvents),2.0f);
    return true;
}
 
void EventDispatcherTest::funEventTouch(Sprite* sprite)
{
    this->_eventDispatcher->removeAllEventListeners();
     
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(EventDispatcherTest::onTouchBeganss,this);
    listener->onTouchMoved = CC_CALLBACK_2(EventDispatcherTest::onTouchMovedss,this);
    listener->onTouchEnded = CC_CALLBACK_2(EventDispatcherTest::onTouchEndedss,this);
    listener->onTouchCancelled = CC_CALLBACK_2(EventDispatcherTest::onTouchCancelledss,this);
    listener->setSwallowTouches(true);//是否向下传递
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,sprite);
}
 
bool EventDispatcherTest::onTouchBeganss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
 
    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());
    Size s = target->getContentSize();
    Rect rect = Rect(0, 0, s.width, s.height);
 
    if (rect.containsPoint(locationInNode))
    {
        label->setString("onTouchBegan......");
        target->setOpacity(180);
        return true;
    }
    return false;
}
void EventDispatcherTest::onTouchMovedss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
    target->setPosition(target->getPosition() + touch->getDelta());
    label->setString("onTouchMoved......");
}
void EventDispatcherTest::onTouchEndedss(Touch* touch,Event* ev)
{
    auto target = static_cast<Sprite*>(ev->getCurrentTarget());
    target->setOpacity(255);
    label->setString("onTouchEnded......");
}
void EventDispatcherTest::onTouchCancelledss(Touch* touch,Event* ev)
{
    label->setString("onTouchCancelled......");
}
 
 
void EventDispatcherTest::funEventKeyboard()
{
    this->_eventDispatcher->removeAllEventListeners();
 
    auto listener = EventListenerKeyboard::create();
    listener->onKeyPressed = CC_CALLBACK_2(EventDispatcherTest::onKeyPressedss,this);
    listener->onKeyReleased = CC_CALLBACK_2(EventDispatcherTest::onKeyReleasedss,this);
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}
 
void EventDispatcherTest::onKeyPressedss(EventKeyboard::KeyCode keycode,Event* ev)
{
    char txt[100] = {};
    sprintf_s(txt,"key %d is Pressed!",(int)keycode);
    label->setString(txt);
}
 
void EventDispatcherTest::onKeyReleasedss(EventKeyboard::KeyCode keycode,Event* ev)
{
    label->setString("key is Released!");
}
 
void EventDispatcherTest::funEventMouse(Sprite* sprite)
{
    this->_eventDispatcher->removeAllEventListeners();
 
    auto listener = EventListenerMouse::create();
    listener->onMouseDown = CC_CALLBACK_1(EventDispatcherTest::onMouseDownss,this);
    listener->onMouseMove = CC_CALLBACK_1(EventDispatcherTest::onMouseMovess,this);
    listener->onMouseUp = CC_CALLBACK_1(EventDispatcherTest::onMouseUpss,this);
    listener->onMouseScroll = CC_CALLBACK_1(EventDispatcherTest::onMouseScrollss,this);
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,sprite);
}
 
void EventDispatcherTest::onMouseDownss(Event* ev)
{
    label->setString("onMouseDown!");
}
void EventDispatcherTest::onMouseMovess(Event* ev)
{
    label->setString("onMouseMove!");
}
void EventDispatcherTest::onMouseUpss(Event* ev)
{
    label->setString("onMouseUp!");
}
void EventDispatcherTest::onMouseScrollss(Event* ev)
{
    label->setString("onMouseScroll!");
}
 
void EventDispatcherTest::funEventCustom()
{
    auto listener = EventListenerCustom::create("custom_event_1",CC_CALLBACK_1(EventDispatcherTest::onEventCustom,this));
    this->_eventDispatcher->addEventListenerWithFixedPriority(listener,1);//添加到事件分發器
}
 
void EventDispatcherTest::dispatcherCustomEvents(float at)
{
    //派發事件custom_event_1  事件內容為字符串custom event test!
    this->_eventDispatcher->dispatchCustomEvent("custom_event_1","custom event test!");
}
 
void EventDispatcherTest::onEventCustom(EventCustom* event)
{
    auto data = static_cast<char*>(event->getUserData());
    label->setString(data);
}
 
void EventDispatcherTest::funEventAcceleration()
{
    //啟動硬件設備
    Device::setAccelerometerEnabled(true); 
 
    auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(EventDispatcherTest::onAcceleration,this));
    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
}
 
void EventDispatcherTest::onAcceleration(Acceleration* acc,Event* event)
{
    char str[100]={};
    sprintf_s(str,"x:%2d,y:%2d,z:%2d,timestamp:%2d",acc->x,acc->y,acc->z,acc->timestamp);
    log(str);
}
 
EventDispatcherTest.cpp

推荐阅读:

【官方文档】事件分发机制

原文地址:https://www.cnblogs.com/dudu580231/p/4565779.html