首页 > 代码库 > cocos2d-x 3.0点击响应
cocos2d-x 3.0点击响应
迄今为止,发现cocos2d-x 3.0最让人惊艳的地方就是更改了点击事件机制。(ps:迄今只看了点击事件这块,捂嘴笑~~~)
cocos2d-x 2.0 只有CCLayer有点击事件处理,需要注册,需要实现onTouchBegan等方法,最坑爹的就是按照优先级来传递点击事件,让人诟病不已。每次遇到由于优先级而造成的点击bug,都有一种崩溃之感。
让人高兴的是,从现在开始,这种情况应该就会很少遇到了。闲话不说,开始正文。
3.0版本中,处理点击事件有两种方式:
1、函数回调
1 // a selector callback 2 void menuCloseCallback(Object* pSender); 3 4 auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png", 5 CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 6 7 void HelloWorld::menuCloseCallback(Object* pSender) 8 { 9 Director::getInstance()->end();10 11 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)12 exit(0);13 #endif14 }
其中CC_CALLBACK_1宏是将函数与对象绑定在一起,1表示这个函数有一个参数。当点击这个按钮时,会调用这个回调函数。
除了基于c++11的这个形式的改变,使用方法与先前相同。
2、Listener消息响应方式
Listener的加入,使得Sprite可以很方便的就可以拥有处理点击事件的能力。再也不用为了写个能够响应事件的Sprite而让去继承Layer了。总觉得class TestSprite : public CCLayer这种定义Sprite的方式是坑人的一种做法。终于可以将其摒弃了。
3.0版本,只需要为Sprite创建一个Listener,然后将Listener与Sprite绑定,并添加到Listener队列内即可,方便至极。
另,每一个Listener也只能和一个Sprite进行绑定,而Listener的clone方法,可以很方便的将listener复制为其他对象可用的listener。
废话少说,上代码最重要:
1 #ifndef __Touchable_Sprite_Test_H__ 2 #define __Touchable_Sprite_Test_H__ 3 4 #include "cocos2d.h" 5 USING_NS_CC; 6 7 class TouchableSpriteTest : public Layer 8 { 9 public:10 CREATE_FUNC(TouchableSpriteTest);11 virtual void onEnter() override;12 virtual void onExit() override;13 };14 15 #endif
1 #include "TouchableSpriteTest.h" 2 3 void TouchableSpriteTest::onEnter() 4 { 5 Layer::onEnter(); 6 Point origin = Director::getInstance()->getVisibleOrigin(); 7 Size size = Director::getInstance()->getVisibleSize(); 8 9 auto containerForSprite1 = Node::create();10 this->addChild(containerForSprite1, 10);11 auto sprite1 = Sprite::create( "images/CyanSquare.png" );12 sprite1->setPosition( origin + Point( size.width * 0.5, size.height * 0.5) + Point( -80, 80 ) );13 containerForSprite1->addChild(sprite1);14 15 auto sprite2 = Sprite::create("images/MagentaSquare.png");16 sprite2->setPosition(origin+Point(size.width/2, size.height/2));17 addChild(sprite2, 20);18 19 auto sprite3 = Sprite::create("images/YellowSquare.png");20 sprite3->setPosition(Point(0, 0));21 sprite2->addChild(sprite3, 1);22 // Make sprite1 touchable23 auto listener1 = EventListenerTouchOneByOne::create();24 25 listener1->setSwallowTouches(true);26 27 listener1->onTouchBegan = [](Touch* touch, Event* event){28 auto target = static_cast<Sprite*>(event->getCurrentTarget());29 30 Point locationInNode = target->convertToNodeSpace(touch->getLocation());31 Size s = target->getContentSize();32 Rect rect = Rect(0, 0, s.width, s.height);33 34 if (rect.containsPoint(locationInNode))35 {36 log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);37 target->setOpacity(180);38 return true;39 }40 return false;41 };42 43 listener1->onTouchMoved = [](Touch* touch, Event* event){44 auto target = static_cast<Sprite*>(event->getCurrentTarget());45 target->setPosition(target->getPosition() + touch->getDelta());46 };47 48 listener1->onTouchEnded = [=](Touch* touch, Event* event){49 auto target = static_cast<Sprite*>(event->getCurrentTarget());50 log("sprite onTouchesEnded.. ");51 target->setOpacity(255);52 if (target == sprite2)53 {54 containerForSprite1->setLocalZOrder(100);55 }56 else if(target == sprite1)57 {58 containerForSprite1->setLocalZOrder(0);59 }60 };61 62 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);63 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);64 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);65 66 Rect s_visibleRect = Director::getInstance()->getOpenGLView()->getVisibleRect();67 Point right = Point(s_visibleRect.origin.x+s_visibleRect.size.width, s_visibleRect.origin.y+s_visibleRect.size.height/2);68 69 auto removeAllTouchItem = MenuItemFont::create("Remove All Touch Listeners ",[&]( Ref* sender ){70 auto senderItem = static_cast<MenuItemFont*>(sender);71 senderItem->setString("Only next item could be clicked ");72 73 _eventDispatcher->removeEventListenersForType( EventListener::Type::TOUCH_ONE_BY_ONE );74 75 auto nextItem = MenuItemFont::create("Next", [&](Ref* sender){76 });77 78 nextItem->setFontSizeObj(16);79 nextItem->setPosition(right + Point(-100, -30));80 81 auto menu2 = Menu::create(nextItem, NULL);82 menu2->setPosition(Point(0, 0));83 menu2->setAnchorPoint(Point(0, 0));84 this->addChild(menu2);85 });86 removeAllTouchItem->setFontSizeObj(16);87 removeAllTouchItem->setPosition(right + Point(-100, 0));88 89 auto menu = Menu::create(removeAllTouchItem, nullptr);90 menu->setPosition(Point(0, 0));91 menu->setAnchorPoint(Point(0, 0));92 addChild(menu);93 }94 95 void TouchableSpriteTest::onExit()96 {97 Layer::onExit();98 }
千里之行始于足下,一切才刚刚开始,想要理解cocos2dx 3.0的点击事件,还是需要深入理解其底层实现的。
大家可以去看 Cocos2d-X3.0 刨根问底(七)----- 事件机制Event源码分析 这应该是一篇好文。
另,本博文参考自:http://blog.csdn.net/fansongy/article/details/12716671
本博主对一切都将不负任何法律责任。