cocos2dx的注册时间监听事件

1、事件处理方法

下面为普通的点击事件监听器(下面简称EventListener)注册部分;注册EventListener需要实现onTouchBegan方法,可以实现onTouchEnded、onTouchCancelled方法,当然如果你想监听触控(鼠标)移动(拖动)监听器需要实现onTouchMoved方法,这里使用Lambda方式简单实现了onTouchBegin方法;

?
1
2
3
4
5
6
7
8
9
10
11
12
auto event =EventListenerTouchOneByOne::create();
event->onTouchBegan= [sprite](Touch *touch, Event *event){
     if (sprite->getBoundingBox().containsPoint(touch->getLocation())){
         ……
         return true ; //此时的返回值很关键;true会继续调用下面的onTouchEnded方法,false不会调用onTouchEnded方法
     }
     return false ;
};
  
event->onTouchEnded= [ this ](Touch *touch, Event *event){
     ……
};

Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(event,sprite);//注册EventListener

在Cocos2dx事件处理系统中并不会区分事件是哪个Node发出的。不管你点击屏幕什么位置(当然点击黑边位置只会打印错误信息),Cocos2dx会将所有的注册EventListener处理方法都会执行一遍;故在事件处理程序中需要添加

if(sprite->getBoundingBox().containsPoint(touch->getLocation()))

来判断点击是否为该注册EventListener;

2、EventListener注册方法

在上述实例中时候用addEventListenerWithSceneGraphPriority方法注册的EventListener,在Cocos2dx中还支持其他几种EventListener的注册方式

(1) addCustomEventListener 添加自定义EventListener

(2) addEventListenerWithFixedPriority 使用优先级添加EventListener

(3) addEventListenerWithSceneGraphPriority 绑定Node方式添加EventListener,优先级为0,优先级最高

addCustomEventListener可以自己定义EventListener,在合适的时候手动分发该事件,这样使用该ID所有自定义EventListener都会被调用,使用这种方法可以实现广播的效果;

addEventListenerWithFixedPriority注册的EventListener会一指存在,知道手动移除该EventListener;

addEventListenerWithSceneGraphPriority注册EventListener时会绑定Node节点,在Node的析构函数(Node从内存删除时调用)中会将Node绑定的Listern移除;节点中使用该方法别较好,当切换Scene时,所有不需要的EventListener都会被移除;

下面分别介绍这三种添加方式

?
1
2
3
4
5
6
EventListenerCustom*EventDispatcher::addCustomEventListener( const std::string &eventName, conststd::function< void (eventcustom*)>& callback)
{
     EventListenerCustom *listener =EventListenerCustom::create(eventName, callback);
     addEventListenerWithFixedPriority(listener, 1 );
     return listener;
}</ void (eventcustom*)>

在addCustomEventListener中:

(1) 使用自定义名称,回调函数,new一个自定义监EventListener

(2) 添加自定义EventListener

顾名思义,该方法的作用是添加一个自定义EventListener,callback为回调函数,需要手动调用Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(…)或

Director::getInstance()->getEventDispatcher()->dispatchEvent(…)来触发

?
1
2
3
4
5
6
7
8
9
10
voidEventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, intfixedPriority)
{  
     if (!listener->checkAvailable())
         return ;
     listener->setAssociatedNode(nullptr);
    listener->setFixedPriority(fixedPriority);
     listener->setRegistered( true );
     listener->setPaused( false );
     addEventListener(listener);
}

在addEventListenerWithFixedPriority方法中:

(1) 判断EventListener可用

(2) 将关联节点设置为null,设置优先级,设置已注册,暂停标志

(3) 将该EventListener添加到EventListener列表中

?
1
2
3
4
5
6
7
8
9
voidEventDispatcher::addEventListenerWithSceneGraphPriority(EventListener*listener, Node* node) {
     //如果_onEvent=false,即没有默认的回调函数
     if (!listener->checkAvailable())
         return ;
     listener->setAssociatedNode(node); // EventListener归属Node
     listener->setFixedPriority( 0 );
     listener->setRegistered( true );
     addEventListener(listener); //添加点击EventListener
}

在addEventListenerWithSceneGraphPriority中

(1) 判断EventListener可用

(2) 设置EventListener关联节点,设置FixedPriority=0

(3) 添加EventListener

3、EventListener注册

?
1
2
3
4
5
6
7
8
9
10
voidEventDispatcher::addEventListener(EventListener* listener)
{
     if (_inDispatch == 0 ) {
         forceAddEventListener(listener); //添加Listener
} else {
         _toAddedListeners.push_back(listener); //将EventListener临时添加到_toAddedListeners中
     }
  
     listener->retain(); //内存管理部分,引用计数+1
}

在addEventListener方法中

(1)判断当前是否在分发事件或执行事件处理方法

(2)若为分发事件或执行事件处理方法,添加EventListener到EventListener列表;否则将EventListener临时添加到toAddedListeners中

Cocos2dx虽然是单线程循环渲染的,但是触摸屏点击、加速传感器等EventListener是在新线程中处理的,如果处理器为多核(现在大多手机是多核的)就会有可能出现多个线程同时执行;在添加EventListener的过程中,正在分发事件或执行事件处理方法,就会将该EventListener添加到_toAddedListeners中,待此时事件处理完毕后,才将_toAddedListeners中EventListener添加到EventListener列表中。具体实现会在下面事件分发中讲述。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
voidEventDispatcher::forceAddEventListener(EventListener* listener)
{
     EventListenerVector* listeners = nullptr;
     EventListener::ListenerID listenerID =listener->getListenerID();
     auto itr = _listenerMap.find(listenerID);   //根据EventListener类型查找EventListener列表
     if (itr == _listenerMap.end()){             //该类型EventListener第一次被添加
         listeners = new EventListenerVector();  //新建EventListener列表
         _listenerMap.insert(std::make_pair(listenerID,listeners));
     } else {
         listeners = itr->second;
     }
     listeners->push_back(listener);         //添加EventListener
     if (listener->getFixedPriority() == 0 ) {
         setDirty(listenerID,DirtyFlag::SCENE_GRAPH_PRIORITY);
         auto node =listener->getAssociatedNode();
         CCASSERT(node != nullptr, "Invalidscene graph priority!" );
         associateNodeAndEventListener(node,listener);
         if (node->isRunning()){
            resumeEventListenersForTarget(node);
         }
     } else {
         setDirty(listenerID,DirtyFlag::FIXED_PRIORITY);
     }
}

在forceAddEventListener方法中

(1)根据EventListener的类型才查找EventListener列表,若该类型EventListener是第一次添加,则新建该类型的EventListener列表

(2)将该EventListener添加到EventListener类表中,在添加EventListener过程中会首先判断_fixedPriority是否为0;若为0则加入_sceneGraphListeners中,否则加入_fixedListeners中

(3)设置对应listenerID的脏数据标志;当_fixedPriority为0时,需将EventListener和注册EventListener的节点Node绑定,插入到_nodeListenersMap中;

EventListener注册完成后,我们关心的就是事件分发了,下一篇将会介绍Cocos2dx-3.2的事件分发机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值