Cocos2dx引擎9-注册事件监听器

1、事件处理方法

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

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都会被移除;

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

EventListenerCustom*EventDispatcher::addCustomEventListener(const std::string &eventName, conststd::function<void(EventCustom*)>& callback)
{
    EventListenerCustom *listener =EventListenerCustom::create(eventName, callback);
    addEventListenerWithFixedPriority(listener,1);
    return listener;
}

在addCustomEventListener中:

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

(2) 添加自定义EventListener

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

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

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列表中

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注册

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列表中。具体实现会在下面事件分发中讲述。

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的事件分发机制

时间: 2024-07-31 03:55:58

Cocos2dx引擎9-注册事件监听器的相关文章

Android设备 cocos2dx 骨骼动画注册事件播放音效,退到后台再返回黑屏问题

最近遇到一个cocos2dx 骨骼动画注册事件播放音效,在骨骼动画播放的时候,按HOME键退到桌面,再次打开游戏的时候,会黑屏. 解决办法如下,可能不是太完美,至少解决了大部分问题. 1.在org.cocos2dx.lib下的 Cocos2dxRenderer.java 中添加native方法 public static native void setIsPause(boolean isPause); 2.在Cocos2dxRenderer.java对应的Java_org_cocos2dx_li

Java 事件监听器

事件 事件是用户在界面上的一个操作(通常使用各种输入设备,如:鼠标.键盘等来完成). 当一个事件发生时,该事件用一个事件对象来表示.事件对象有对应的事件类.不同的事件类描述不同类型的用户动作.事件类包含在java.awt.event和javax.swing.event包中. 事件源 产生事件的组件叫事件源.在一个按钮上单击鼠标时,该按钮就是事件源,会产生一个ActionEvent类型的事件. 事件处理器(事件处理方法) 事件处理器是一个接收事件对象并进行相应处理的方法.事件处理器包含在一个类中,

Spring事件监听器源码

Spring 自定义了继承 JDK 事件监听器的接口ApplicationListener<E extends ApplicationEvent> extends EventListener,用来监听 Spring 应用程序中的事件:自定义了继承 JDK 事件对象的抽象类ApplicationEvent extends EventObject,用来表示 Spring 应用程序中的事件类型.容器启动刷新过程中,可以定义事件监听器,来监听应用程序上下文事件ApplicationContextEve

cocos2dx+lua注册事件函数详解 事件

coocs2dx 版本 3.1.1 registerScriptTouchHandler             注册触屏事件 registerScriptTapHandler                  注册点击事件 registerScriptHandler                         注册基本事件 包括 触屏 层的进入 退出 事件 registerScriptKeypadHandler           注册键盘事件 registerScriptAccelera

cocos2d-x之为label添加事件监听器,单点触摸

在bool HelloWorld::init() 1 //获取可见区域的大小 2 Size visibleSize = Director::getInstance()->getVisibleSize(); 3 //定义一个文本,显示内容 4 auto label = LabelTTF::create("Chick me", "Courier", 30); 5 //定义label的位置 6 label->setPosition(Point(visibleS

js事件监听器用法实例详解-注册与注销监听封装

本文实例讲述了js事件监听器用法.分享给大家供大家参考.具体分析如下: 1.当同一个对象使用.onclick的写法触发多个方法的时候,后一个方法会把前一个方法覆盖掉,也就是说,在对象的onclick事件发生时,只会执行最后绑定的方法.而用事件监听则不会有覆盖的现象,每个绑定的事件都会被执行.如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 window.onload = function(){   var btn = document.getElementById("yuanEv

Cocos2d-x 3.2 EventDispatcher事件分发机制

本文转载于Cocos2d-x v3.2学习笔记中的(九)事件分发机制(EventDispatcher) EventDispatcher事件分发机制先创建事件,注册到事件管理中心_eventDispatcher,通过发布事件得到响应进行回调,完成事件流. 有五种不同的事件机制: EventListenerTouch 响应触控事件 EventListenerKeyboard 响应键盘事件 EventListenerAcceleration 响应加速器事件 EventListenMouse 响应鼠标事

[原创]java WEB学习笔记48:其他的Servlet 监听器:域对象中属性的变更的事件监听器 (3 个),感知 Session 绑定的事件监听器(2个)

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

Android事件监听器Event Listener

在 Android 中,我们可以通过事件处理使UI与用户互动(UI Events). UI的用户事件处理,即View处理用户的操作,在应用程序中几乎不可避免.View是重要的类,它是与用户互动的前线:在Android框架的设计中,以事件监听器(event listener)的方式來处理UI的用户事件. Android框架提供了非常良好的UI事件处理机制.View是绘制UI的类,每个View对象都可以向Android框架注册一个事件监听器.每个事件监听器都包含一个回调函数(callback met