cocos2d-x 3.0點擊響應


迄今為止,發現cocos2d-x 3.0最讓人驚艷的地方就是更改了點擊事件機制。(ps:迄今只看了點擊事件這塊,捂嘴笑~~~)

cocos2d-x 2.0 只有CCLayer有點擊事件處理,需要注冊,需要實現onTouchBegan等方法,最坑爹的就是按照優先級來傳遞點擊事件,讓人詬病不已。每次遇到由於優先級而造成的點擊bug,都有一種崩潰之感。

讓人高興的是,從現在開始,這種情況應該就會很少遇到了。閑話不說,開始正文。

3.0版本中,處理點擊事件有兩種方式:

1、函數回調

函數回調是最簡單的響應形式,一直以來被用於MenuItem中的點擊處理。在新版本中,此處發生了些小改變,也就是采用了CC_CALLBACK系列,有不明白的可以去看帖子: c++11特性與cocos2d-x 3.0之std::bind與std::function

 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 #endif
14 }

其中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 touchable
23     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

本博主對一切都將不負任何法律責任。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM