cocos2dx 3.2中的觸控機制

塵封的記憶0發表於2015-01-18

在cocos2dx 3.2版本中,廢棄了以往2.x版本的寫法,我們先來看一下Layer.h中的一段程式碼

 //單點觸控
  virtual bool onTouchBegan(Touch *touch, Event *unused_event); 
  virtual void onTouchMoved(Touch *touch, Event *unused_event); 
  virtual void onTouchEnded(Touch *touch, Event *unused_event); 
  virtual void onTouchCancelled(Touch *touch, Event *unused_event);
  //多點觸控
  virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
  virtual void onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event);
  virtual void onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event);
  virtual void onTouchesCancelled(const std::vector<Touch*>&touches, Event *unused_event);

單點觸控:(即只有註冊的Layer才能接收觸控事件)

 onTouchBegan:如果返回true: 本層的後續Touch事件可以被觸發,並阻擋向後層傳遞

                                 如果返回false, 本層的後續Touch事件不能被觸發,並向後傳遞

簡單點來說, 如果

1.Layer 只有一層的情況:

virtual  bool  onTouchBegan( CCTouch  *pTouch,  CCEvent  *pEvent);

a.返回false,則ccTouchMoved(),ccTouchEnded()不會再接收到訊息

b.返回true,則ccTouchMoved(),ccTouchEnded()可以接收到訊息

2.Layer 有多層的情況:

virtual  bool  onTouchBegan( CCTouch  *pTouch,  CCEvent  *pEvent);

a.返回false,則本層的onTouchMoved(),onTouchEnded()不會再接收到訊息,但是本層之下的其它層會接收到訊息

b.返回true,則本層的onTouchMoved(),onTouchEnded()可以接收到訊息,但是本層之下的其它層不能再接收到訊息

單點觸控簡單用法:

在Layer中新增如下程式碼, 重寫onTouchxxx函式

auto dispatcher = Director::getInstance()->getEventDispatcher();
  auto listener = EventListenerTouchOneByOne::create();
  listener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan,this);
  listener->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved,this);
  listener->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded,this);
  listener->setSwallowTouches(true);//不向下傳遞觸控
  dispatcher->addEventListenerWithSceneGraphPriority(listener,this);

 listener->setSwallowTouches(true),不向下觸控,簡單點來說,比如有兩個sprite ,A 和 B,A在上B在下(位置重疊),觸控A的時候,B不會受到影響

  listener->setSwallowTouches(false)反之,向下傳遞觸控,觸控A也等於觸控了B


多點觸控點單用法(多個Layer獲取螢幕事件):

auto dispatcher = Director::getInstance()->getEventDispatcher();
  auto listener1 = EventListenerTouchAllAtOnce::create();
  listener1->onTouchesBegan = CC_CALLBACK_2(GameLayer::onTouchesBegan,this);
  listener1->onTouchesMoved = CC_CALLBACK_2(GameLayer::onTouchesMoved,this);
  listener1->onTouchesEnded = CC_CALLBACK_2(GameLayer::onTouchesEnded,this);
  dispatcher->addEventListenerWithSceneGraphPriority(listener1,this);
或者setTouchEnabled(true),然後重寫layer的onTouchsxxx函式

關於eventDispatcher: 

  • 獲取方法:

  • auto dispatcher = Director::getInstance()->getEventDispatcher();

事件監聽器包含以下幾種:

  • 觸控事件 (EventListenerTouch)
  • 鍵盤響應事件 (EventListenerKeyboard)
  • 加速記錄事件 (EventListenerAcceleration)
  • 滑鼠響應事件 (EventListenerMouse)
  • 自定義事件 (EventListenerCustom)

    以上事件監聽器統一由  _eventDispatcher  來進行管理。


優先權:

1.優先順序越低,越先響應事件

2.如果優先順序相同,則上層的(z軸)先接收觸控事件

有兩種方式將 事件監聽器 listener1 新增到 事件排程器_eventDispatcher 中: 

void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
    void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
程式碼展開一下:
void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
{
  CCASSERT(listener && node, "Invalid parameters.");
  CCASSERT(!listener->isRegistered(), "The listener has been registered.");
  
  if (!listener->checkAvailable())
    return;
  
  listener->setSceneGraphPriority(node);
  listener->setFixedPriority(0);
  listener->setRegistered(true);
  
  addEventListener(listener);
}
void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
{
  CCASSERT(listener, "Invalid parameters.");
  CCASSERT(!listener->isRegistered(), "The listener has been registered.");
  CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");
  
  if (!listener->checkAvailable())
    return;
  
  listener->setSceneGraphPriority(nullptr);
  listener->setFixedPriority(fixedPriority);
  listener->setRegistered(true);
  listener->setPaused(false);

  addEventListener(listener);
}

(1)addEventListenerWithSceneGraphPriority 的事件監聽器優先順序是0, 而且在 addEventListenerWithFixedPriority 中的事件監聽器的優先順序不可以設定為 0,因為這個是保留給 SceneGraphPriority 使用的。


(2)另外,有一點非常重要,FixedPriority listener新增完之後需要手動remove,而SceneGraphPriority listener是跟node繫結的,在node的解構函式中會被移除。 

移除方法:
dispatcher->removeEventListener(listener);




Cocos新手學習必備原始碼啊,大量本人寫的的原始碼(有些商業的淘寶店木有放出來,可以私聊),ARPG,動作射擊,闖關益智,可學習可運營 個人淘寶店,適合新手,我還可以做技術支援,幫助換皮,帶新手等https://shop141567464.taobao.com/?spm=a313o.7775905.1998679131.d0011.pzUIU4

不懂的可以加我的QQ群: 239982941(cocos2d-x 3.x學習群)歡迎你的到來哦,看了博文給點腳印唄,謝謝啦~~


相關文章