【嘮叨】
在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、主要函數
包含監聽器的添加、刪除、暫停、恢復,優先級的設置,手動分發事件等。
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
|
class EventDispatcher : public Ref
{
void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
EventListenerCustom* addCustomEventListener( const std::string &eventName, const std::function< void (EventCustom*)>& callback);
void removeEventListener(EventListener* listener);
void removeEventListenersForType(EventListener::Type listenerType);
void removeEventListenersForTarget(Node* target, bool recursive = false );
void removeCustomEventListeners( const std::string& customEventName);
void removeAllEventListeners();
void pauseEventListenersForTarget(Node* target, bool recursive = false );
void resumeEventListenersForTarget(Node* target, bool recursive = false );
void setPriority(EventListener* listener, int fixedPriority);
void setEnabled( bool isEnabled);
bool isEnabled() const ;
void dispatchEvent(Event* event);
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
單點觸摸監聽器相關:
1
2
3
4
5
6
7
8
|
static EventListenerTouchOneByOne* create();
std::function< bool (Touch*, Event*)> onTouchBegan;
std::function< void (Touch*, Event*)> onTouchMoved;
std::function< void (Touch*, Event*)> onTouchEnded;
std::function< void (Touch*, Event*)> onTouchCancelled;
|
使用舉例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
auto dispatcher = Director::getInstance()->getEventDispatcher();
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 );
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
多點觸摸監聽器相關:
1
2
3
4
5
6
7
8
|
static EventListenerTouchAllAtOnce* create();
std::function< void ( const std::vector<Touch*>&, Event*)> onTouchesBegan;
std::function< void ( const std::vector<Touch*>&, Event*)> onTouchesMoved;
std::function< void ( const std::vector<Touch*>&, Event*)> onTouchesEnded;
std::function< void ( const std::vector<Touch*>&, Event*)> onTouchesCancelled;
|
使用舉例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
auto dispatcher = Director::getInstance()->getEventDispatcher();
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 );
dispatcher->addEventListenerWithSceneGraphPriority(touchesListener, this );
void onTouchesBegan( const std::vector<Touch*>& touches, Event *unused_event) { CCLOG( "began" ); }
void onTouchesMoved( const std::vector<Touch*>& touches, Event *unused_event) { CCLOG( "moved" ); }
void onTouchesEnded( const std::vector<Touch*>& touches, Event *unused_event) { CCLOG( "ended" ); }
void onTouchesCancelled( const std::vector<Touch*>&touches, Event *unused_event) { CCLOG( "cancelled" ); }
|