于cocos2d-x v3.0alpha0加入

http://blog.csdn.net/huang_hws/article/details/18554749

介绍

cocos2d-x 3.0介绍了一种新的响应用户事件的机制,本文档介绍它的使用。
基础:
  • 事件监听器封装了事件处理代码
  • 事件派发器通知用户事件的监听器
  • 事件对象包含了事件的相关信息
要响应事件就先必须创建有EventListener,总共有五类EventListener:
  • EventListenerTouch- responds to touch events
  • EventListenerKeyboard- responds to keyboard events
  • EventListeneracceleration- reponds to accelerometer events
  • EventListenMouse- responds to mouse events
  • EventListenerCustom- responds to custom events
创建好EventListener之后,将你的事件处理代码添加到相关的事件监听器中(如:onTouchBegan添加到EventListenerTouch监听器,或者onKeypressed添加到键盘事件监听器)。
接下来就是用Eventdispatcher注册你的事件监听器。
当事件发生时(用户触碰屏幕,键盘输入等),Eventdispatcher就会分配一个事件对象(如EventTouch,EventKeyboard)到适当的事件监听器来调用你的回调函数。每一个事件对象都包含有该事件的相关信息(如触碰事件的座标轴)。

例子

在下面的例子中,我们将在场景中添加三个互相重叠的按钮。每一个都会响应触碰事件。

创建三个sprite作为图片按钮

   auto sprite1 = Sprite::create("Images/CyanSquare.png");
   sprite1->setPosition(origin+Point(size.width/2, size.height/2) + Point(-80, 80));
   addChild(sprite1,153)">10);

   auto sprite2 = Sprite::create("Images/magentaSquare.png");
   sprite2->setPosition(origin+Point(size.width/2));
   addChild(sprite2,153)">20);

   auto sprite3 = Sprite::create("Images/YellowSquare.png");
   sprite3->setPosition(Point(0,153)">0));
   sprite2->addChild(sprite3,153)">1);


创建一个单一的事件监听器并且实现回调

(注意到下面的例子中使用了C++11的lambda表达式来实现回调,再往下的键盘事件例子用另外一种方式来写回调函数,使用的就是CC_CALLBACK_N宏)
PS:lambda表达式看起来碉堡的样子,翻译者表达除了知道它跟js中的匿名函数一样之外,不知道它还有啥其他的特点。
    //Create a "one by one" touch event listener (processes one touch at a time)
    auto listener1 = EventListenerTouchOneByOne::create();
    // When "swallow touches" is true,then returning 'true' from the onTouchBegan method will "swallow" the touch event,preventing other listeners from using it.
    listener1->setSwallowtouches(true);

    // Example of using a lambda expression to implement onTouchBegan event callback function
    listener1->onTouchBegan = [](Touch* touch, Event* event){
        // event->getCurrentTarget() returns the *listener's* sceneGraPHPriority node.
        auto target = static_cast<Sprite*>(event->getCurrentTarget());

        //Get the position of the current point relative to the button
        Point locationInNode = target->convertToNodeSpace(touch->getLocation());
        Size s = target->getContentSize();
        Rect rect = Rect(s.width, s.height);

        //Check the click area
        if (rect.containsPoint(locationInNode))
        {
            log("sprite began... x = %f,y = %f", locationInNode.x, locationInNode.y);
            target->setopacity(180);
            return true;
        }
        return false;
    };

    //Trigger when moving touch
    listener1->onTouchMoved = [](Touch* touch, Event* event){
        auto target = static_cast<Sprite*>(event->getCurrentTarget());
        //Move the position of current button sprite
        target->setPosition(target->getPosition() + touch->getDelta());
    };

    //Process the touch end event
    listener1->onTouchEnded = [=](Touch* touch, Event* event){
        auto target = static_cast<Sprite*>(event->getCurrentTarget());
        log("sprite ontouchesEnded.. ");
        target->setopacity(255);
        //Reset zOrder and the display sequence will change
        if (target == sprite2)
        {
            sprite1->setZOrder(100);
        }
        else if(target == sprite1)
        {
            sprite1->setZOrder(0);
        }
    };

添加一个事件监听器到事件派发器

//Add listener
    _eventdispatcher->addEventListenerWithSceneGraPHPriority(listener1, sprite1);
    _eventdispatcher->addEventListenerWithSceneGraPHPriority(listener1->clone(), sprite2);
    _eventdispatcher->addEventListenerWithSceneGraPHPriority(listener1->clone(), sprite3);
_eventdispatcher是Node的一个属性,使用它来管理当前节点(Scene,Layer和Sprite)不同事件的分配。
注意:上面的例子中在第二次以后调用addEventListenerWithSceneGraPHPriority使用clone()方法是因为每一个事件监听器只能被添加一次,addEventListenerWithSceneGraPHPriority函数和addEventListenerWithFixedPriority函数会在添加事件监听器时设置一个已注册标识,一旦设置了标识,就不能再用于注册事件监听了。
还有一个需要注意的:如果是固定优先值的监听器添加到一个节点(addEventListenerWithFixedPriority),那当这个节点被移除时必须同时手动移除这个监听器,但是添加场景图优先监听器到节点(addEventListenerWithSceneGraPHPriority)就不用这么麻烦,监听器和节点是绑定好的,一旦节点的析构函数被调用,监听器也会同时被移除。

新的触碰制

乍看之下新的事件处理机制好像比2.x版本的事件机制更加繁琐。但是在旧版本中,当你继承了一个被代理的类,例如一个定义了onTouchBegan()方法的类,那你的事件处理将会进入这些被代理的方法里。
新的事件机制移除掉了代理的事件处理逻辑,将事件处理封装到监听器里,通过以下步骤来实现监听逻辑:
  1. 一个sprite可以将事件监听器添加到SceneGraPHPriority的事件派发器(场景图优先事件派发器),一个事件触发时,回调函数将按它们的绘制次序来调用,即在场景前的优先调用;
  2. 处理事件逻辑时,根据不同的情景来调用回调(识别点击区域,设置点击元素的透明度)来播放点击效果。

FixedPriority和SceneGraPHPriority

事件派发器通过优先权来决定先执行哪个监听器。
  • FixedPriority 整形值。低权值的事件监听器将优于高权值的事件监听器
  • SceneGraPHPriority Node的指针。Node的z顺序高的(绘制于顶部的)节点将优于z顺序低的节点。这将保证了诸如触碰事件的自顶向下传播

其他的事件派发处理模块

除了触碰事件响应,现在的模块也使用相同的事件处理方式。

键盘事件

除了键盘,设备上的菜单也可以使用这个监听器来处理事件。
上面的触碰事件(原文作者走神,说是鼠标事件),我们用了lambda表达式创建回调函数。我们同时也可以用下面的方法使用CC_CALLBACK_N来绑定已定义的函数:
//Initializing and binding 
    auto listener = EventListenerKeyboard::create();
    listener->onKeypressed = CC_CALLBACK_2(KeyboardTest::onKeypressed, this);
    listener->onkeyreleased = CC_CALLBACK_2(KeyboardTest::onkeyreleased, this);

    _eventdispatcher->addEventListenerWithSceneGraPHPriority(listener, this);

    // Implementation of the keyboard event callback function prototype
    void KeyboardTest::onKeypressed(EventKeyboard::KeyCode keyCode, Event* event)
    {
        log("Key with keycode %d pressed", keyCode);
    }

    void KeyboardTest::onkeyreleased(EventKeyboard::KeyCode keyCode,68)">"Key with keycode %d released", keyCode);
    }   

加速计事件

使用加速计事件,需要先启用设备的加速计:
Device::setAccelerometerEnabled(true);
然后创建相关的监听器:
    auto listener = EventListeneracceleration::create(CC_CALLBACK_2(AccelerometerTest::onacceleration, this));
    _eventdispatcher->addEventListenerWithSceneGraPHPriority(listener,136)">// Implementation of the accelerometer callback function prototype
    void AccelerometerTest::onacceleration(acceleration* acc, Event* event)
    {
        //  Processing logic here 
    }

鼠标事件

v3.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,136)">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,153)">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时,当前node里的所有已注册监听器将被移除,删除特定的监听器才是推荐的方式。
注意:使用removeAll后,菜单事件也不会响应,因为它需要接收触碰事件。


原文地址:http://www.cocos2d-x.org/docs/manual/framework/native/input/event-dispatcher/en

cocos2d-x v3.0 事件派发机制的更多相关文章

  1. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码

    这篇文章主要介绍了HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. 浅谈html5之sse服务器发送事件EventSource介绍

    本篇文章主要介绍了浅谈html5之sse服务器发送事件EventSource介绍,具有一定的参考价值,有兴趣的可以了解一下

  5. HTML5 拖放(Drag 和 Drop)详解与实例代码

    本篇文章主要介绍了HTML5 拖放(Drag 和 Drop)详解与实例代码,具有一定的参考价值,有兴趣的可以了解一下

  6. ios – Swift中的非响应流委托

    所以我在Swift中使用套接字并试图将应用程序与我的服务器连接起来.我让应用程序连接到服务器的IP地址,并在服务器上使用netcat进行测试.在执行期间,应用程序的控制台输出显示它已成功连接到服务器.但是,流委托似乎没有响应.当我输入netcat时,app控制台没有打印任何内容.我已经搜索了很长一段时间,发现我的实现与其他实现非常相似.也许我在这里遗漏了一些我看不到的东西.任何想到这个问题的人都将不胜感激!

  7. ios – UIScrollView内容不允许用户交互

    我有一个启用了分页的UIScrollView,如下所示:在UIScrollView中,我添加了几个UIWebViews,并将其启用的交互设置为是这样的.它打破了UIScrollView上的分页和所有触摸.如果我将用户交互设置为NO,则页面有效,但我无法在UIWebView中突出显示文本.我试着像下面那样对UIScrollView进行子类化,但是会出现同样的情况.任何的想法?

  8. ios – 如何知道用户在iPhone中的播放控件上单击快进和快退按钮

    还是有其他方法吗?

  9. ios – 如何在使用隐式动画为CALayer设置动画时继承动画属性

    我试图使用隐式动画在CALayer上设置自定义属性的动画:在-actionForKey:方法我需要返回动画,负责插值.当然,我必须以某种方式告诉动画如何检索动画的其他参数.有关如何实现这一点的任何想法?

  10. ios – touchesMoved在iPhone 6s及以后的单点击中被调用

    解决方法可能是更高分辨率的屏幕对任何移动都更敏感.当你敲击时,你实际上可能正在滚动你的手指,使它看起来像一个小动作.两种可能的解决方>在touchesMoved:方法中检查触摸移动了多远.如果这是一个非常小的举动,请忽略它以进行_isTapped检查.>而不是覆盖触摸…

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部