cocos2dx 观察者模式

cocos2dx 观察者模式,第1张

概述cocos2d-x v3.0alpha0加入 介绍 cocos2d-x 3.0介绍了一种新的响应用户事件的机制,本文档介绍它的使用。 基础: 事件监听器封装了事件处理代码 事件派发器通知用户事件的监听器 事件对象  包含了事件的相关信息 要响应事件就先必须创建有EventListener,总共有五类EventListener: EventListenerTouch - responds to to

cocos2d-x v3.0Alpha0加入

介绍 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)就不用这么麻烦,监听器和节点是绑定好的,一旦节点的析构函数被调用,监听器也会同时被移除。 新的触碰制 @H_301_819@乍看之下新的事件处理机制好像比2.x版本的事件机制更加繁琐。但是在旧版本中,当你继承了一个被代理的类,例如一个定义了ontouchBegan()方法的类,那你的事件处理将会进入这些被代理的方法里。 新的事件机制移除掉了代理的事件处理逻辑,将事件处理封装到监听器里,通过以下步骤来实现监听逻辑: 一个sprite可以将事件监听器添加到SceneGraPHPriority的事件派发器(场景图优先事件派发器),一个事件触发时,回调函数将按它们的绘制次序来调用,即在场景前的优先调用; 处理事件逻辑时,根据不同的情景来调用回调(识别点击区域,设置点击元素的透明度)来播放点击效果。
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后,菜单事件也不会响应,因为它需要接收触碰事件。 总结

以上是内存溢出为你收集整理的cocos2dx 观察者模式全部内容,希望文章能够帮你解决cocos2dx 观察者模式所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1026256.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存