Cocos2d-x 3.0 點擊互動的四種處理

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   strong   

1、概述     遊戲也好,程式也好,只有能與使用者互動才有意義。手機上的互動大致可以分為兩部分:點擊和輸入。其中點擊更為重要,幾乎是遊戲中全部的互動。在Cocos2d-x 3.0中,更改了dispatch機制。同時加入了兩種新的互動形式:listener 和touchEvent回調。加上先前版本中的點擊函數回調,與重寫layer層的touch訊息響應,構成了一個相對完整的互動模式。先上一張Demo的圖: 2、四種點擊  1、函數回調 函數回調是最簡單的響應形式,一直以來被用於MenuItem中的點擊處理。在新版本中,此處發生了些小改變。我們可以看到在產生的程式中相關代碼是這樣的:  [cpp] view plaincopyprint?
  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.     Director::getInstance()->end(); 
  9.  
  10. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) 
  11.     exit(0); 
  12. #endif 
// a selector callbackvoid menuCloseCallback(Object* pSender);auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",                        CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));void HelloWorld::menuCloseCallback(Object* pSender){    Director::getInstance()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)    exit(0);#endif}
 

    其中CC_CALLBACK_1宏是將函數與對象綁定在一起,1表示這個函數有一個參數。當點擊這個按鈕時,會調用這個回呼函數。

    除了基於c++11的這個形式的改變,使用方法與先前相同。

 

此種方式已經被捨棄,可以使用第四種方法做替代。

   2、Layer的touch訊息響應

    雖然重寫了底層的dispatch,但對這層的使用影響並不大。我們同樣需要重寫:

 

[cpp] view plaincopyprint?
  1. //單點響應 
  2. virtual bool onTouchBegan(Touch* touch, Event  *event) override; 
  3. virtual void onTouchMoved(Touch* touch, Event  *event) override; 
  4. virtual void onTouchEnded(Touch* touch, Event  *event) override; 
  5. virtual void onTouchCancelled(Touch *touch, Event *event) override; 
  6.  
  7. //多點響應 
  8. virtual bool onTouchesBegan(Touch* touch, Event  *event) override; 
  9. virtual void onTouchesMoved(Touch* touch, Event  *event) override; 
  10. virtual void onTouchesEnded(Touch* touch, Event  *event) override; 
  11. virtual void onTouchesCancelled(Touch *touch, Event *event) override; 
//單點響應virtual bool onTouchBegan(Touch* touch, Event  *event) override;virtual void onTouchMoved(Touch* touch, Event  *event) override;virtual void onTouchEnded(Touch* touch, Event  *event) override;virtual void onTouchCancelled(Touch *touch, Event *event) override;//多點響應virtual bool onTouchesBegan(Touch* touch, Event  *event) override;virtual void onTouchesMoved(Touch* touch, Event  *event) override;virtual void onTouchesEnded(Touch* touch, Event  *event) override;virtual void onTouchesCancelled(Touch *touch, Event *event) override;

 

    重寫這些函數來對layer的點擊做處理。當然,我們需要:

 

[cpp] view plaincopyprint?
  1. setTouchEnabled(true)。 
setTouchEnabled(true)。

 

   此外有個小改動。對於單點觸控響應,可以調用:

 

[cpp] view plaincopyprint?
  1. //設定為單點響應 
  2. setTouchMode(Touch::DispatchMode::ONE_BY_ONE); 
  3. //設定為多點響應(預設) 
  4. setTouchMode(Touch::DispatchMode::ALL_AT_ONCE); 
//設定為單點響應setTouchMode(Touch::DispatchMode::ONE_BY_ONE);//設定為多點響應(預設)setTouchMode(Touch::DispatchMode::ALL_AT_ONCE);

 

    進行設定,而不需要再用設定Delegate的方式來做了。

 

    3、TouchEvent響應    這是新加入的回應程式式。它主要是使用在UIWidget上的。可以將其看做是函數回調的一個擴充,為更多的響應處理提供可能。使用方法大致是:  [cpp] view plaincopyprint?
  1. //聲明 
  2. void touchButton(Object* object,TouchEventType type); 
  3.  
  4. //掛接到控制項上 
  5. uiButton->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton)); 
  6.  
  7. //實現 
  8. void HelloWorld::touchButton(Object* object,TouchEventType type) 
  9.     LabelTTF* label; 
  10.     switch (type) 
  11.     { 
  12.     case TouchEventType::TOUCH_EVENT_BEGAN: 
  13.         label = static_cast<LabelTTF*>(getChildByTag(11)); 
  14.         label->setString("按下按鈕"); 
  15.         break; 
  16.     case TouchEventType::TOUCH_EVENT_MOVED: 
  17.         label = static_cast<LabelTTF*>(getChildByTag(11)); 
  18.         label->setString("按下按鈕移動"); 
  19.         break; 
  20.     case TouchEventType::TOUCH_EVENT_ENDED: 
  21.         label = static_cast<LabelTTF*>(getChildByTag(11)); 
  22.         label->setString("放開按鈕"); 
  23.         break; 
  24.     case TouchEventType::TOUCH_EVENT_CANCELED: 
  25.         label = static_cast<LabelTTF*>(getChildByTag(11)); 
  26.         label->setString("取消點擊"); 
  27.         break; 
  28.     default: 
  29.         break; 
  30.     } 
//聲明void touchButton(Object* object,TouchEventType type);//掛接到控制項上uiButton->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton));//實現void HelloWorld::touchButton(Object* object,TouchEventType type){LabelTTF* label;switch (type){case TouchEventType::TOUCH_EVENT_BEGAN:label = static_cast<LabelTTF*>(getChildByTag(11));label->setString("按下按鈕");break;case TouchEventType::TOUCH_EVENT_MOVED:label = static_cast<LabelTTF*>(getChildByTag(11));label->setString("按下按鈕移動");break;case TouchEventType::TOUCH_EVENT_ENDED:label = static_cast<LabelTTF*>(getChildByTag(11));label->setString("放開按鈕");break;case TouchEventType::TOUCH_EVENT_CANCELED:label = static_cast<LabelTTF*>(getChildByTag(11));label->setString("取消點擊");break;default:break;}}

   因為所有的UIWidget都要添加到UILayer上,而UILayer通常作為UI的Widget都會在最上層,所以可以“基本上”認為這種使用方式會優先於其他方式處理點擊訊息。因為UILayer也會有層級的改變,比如它和MenuItem之間的關係。所以說“基本上”。

4、Listener訊息回應程式式

    這種實現也是新加入的。它更像是點擊的一個層次過濾器。點擊時,在listener隊裡中進行過濾。每一個listener檢查自己儲存的touch訊息響應是否會被觸發。一層一層過濾,最後在到Layer的touch訊息響應。

    我覺得它的設計的初衷是為任意sprite提供一套自己制定的點擊響應。但這樣的實現仍然要寫很多條件判斷,沒有能夠控制項化。可能我的理解有些偏差,歡迎討論。

    它被設計成一個全域點擊響應控制。具體的用法大致是這樣:

 

 

[cpp] view plaincopyprint?
  1. //auto dispatcher = EventDispatcher::getInstance(); 
  2. //  auto myListener = EventListenerTouch::create(Touch::DispatchMode::ONE_BY_ONE); 
  3. auto dispatcher = Director::getInstance()->getEventDispatcher(); 
  4. auto myListener = EventListenerTouchOneByOne::create(); 
  5.  
  6. //如果不加入此句訊息依舊會向下傳遞 
  7. myListener->setSwallowTouches(true); 
  8.  
  9. myListener->onTouchBegan = [=](Touch* touch,Event* event) 
  10.     //some check 
  11.     if (pass) 
  12.     { 
  13.         return true; 
  14.     } 
  15.     return false; 
  16. }; 
  17.  
  18. myListener->onTouchMoved = [=](Touch* touch,Event* event) 
  19.     //do something 
  20. }; 
  21.  
  22. myListener->onTouchEnded = [=](Touch* touch,Event* event) 
  23.     //do something 
  24. }; 
  25.  
  26. dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite1); 
  27. dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite2); 
//auto dispatcher = EventDispatcher::getInstance();//auto myListener = EventListenerTouch::create(Touch::DispatchMode::ONE_BY_ONE);auto dispatcher = Director::getInstance()->getEventDispatcher();auto myListener = EventListenerTouchOneByOne::create();//如果不加入此句訊息依舊會向下傳遞myListener->setSwallowTouches(true);myListener->onTouchBegan = [=](Touch* touch,Event* event){    //some check    if (pass)    {        return true;    }    return false;};myListener->onTouchMoved = [=](Touch* touch,Event* event){//do something};myListener->onTouchEnded = [=](Touch* touch,Event* event){//do something};dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite1);dispatcher->addEventListenerWithSceneGraphPriority(myListener,mySprite2);

 

    其原理是在dispatcher中檢查listener列表,例如myListener或加進來的其他listener。然後每個listener檢查自己中的Item看能否達到檢查條件,例如:mySprite1,mySprite2。然後執行相應的操作。但這樣的話,當控制項很多的時候,每一次事件都進行這種雙鏈表的檢查操作不知會不會影響些效能?

3、執行個體

    光說不練假把式,於是就動手寫了一個上面的Demo:

 

    點擊背景地區可以移動整個情境,點擊藍色小方塊可以半透明移動它,點擊藍色按鈕可以更改文字,顯示狀態。點擊右下角按鈕退出程式。

    項目配置可參照:

Cocos2d-x 3.0 開發(十六)cocos2dx-3.0beta版建立新項目並載入CocoStudio匯出檔案

 

4、總結

    根據不同的互動需要,選擇不同的實現方式,會更有利於我們的維護和擴充,相應例子可以在下面下載。

 

 

    Demo下載:http://download.csdn.net/detail/fansongy/6399291 不要資源分,覺得好勞煩點下 “頂” ~

   Demo For Beta2 下載:http://download.csdn.net/detail/fansongy/6892047

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.