cocos2d-x 一道簡單面試題,觸摸事件的重新分發

轉載請註明出處 http://blog.csdn.net/rct1985


前段時候換工作時,去觸控科技面試,面試官問了這麼一個問題。”當彈出一個新窗口時,如果屏蔽掉下面層的觸摸事件?“
這個問題對於接觸cocos2d引擎一段時間的同學來說,都不算難。當時我想到了兩種解決方案,也是在之前項目中用到過的:


一、加一個屏蔽層,TouchMaskLayer, 它的寫法差不多就是 
a. CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuTouchPriority, true);
b. ccTouchBegan 中 return true;
二、先把本層的觸摸開關手動關掉,再加彈出層,實現方式差不多是 :
a. 本層實現 onControl() 和 lostControl(), 把本層觸摸相關的對象(CCLayer, CCMenu CCEditbox,...)setTouchEnable(true/false), 
b.彈出新層之前,調用lostControl(), 新層關掉時回調onControl()


第一種寫法簡單粗暴,簡單的邏輯可以直接這麼用。它的問題是,如果彈出層上需要多點觸摸的話,這是行不通的,因爲多點觸摸優先級沒有TouchMaskLayer高,它將得不到事件。
第二種方法,是和三國塔防程序同事楊新寧,魏萊一起討論而來的。這種方式我一直在用,除了麻煩一些外,沒發現任何問題。其實這種方式也沒想象中的麻煩,因爲一個場景中可以有觸摸事件的對象也就那幾個。


我問他們有什麼更好的方式時,捕魚2主程汪東林(在些表示感謝)說了他們的做法,自己處理事件分發。我根據這個想法自己做了個彈出層的基類UpperLayer


//
//  UpperLayer.h
//  MythLeague
//
//  Created by raochongtao on 13-6-26.
//
//

/* 功能
 * 1. 彈出層的基類, 比下層擁有更高的優先級, 用於屏蔽下層,及本層外觸摸事件
 * 2. 提供一個容量,及相應方法,用於裝納需要處理事件的對象 CCTouchDelegate*對象, 
 */


#ifndef __MythLeague__UpperLayer__
#define __MythLeague__UpperLayer__

#include "Global/Constants.h"
#include "CommonLayer/TouchLogicLayer.h"

class UpperLayer : public  TouchLogicLayer{
    
public:
    UpperLayer();
    virtual ~UpperLayer();
    
    bool init();
        
    void onEnter();
    void onExit();
    void registerWithTouchDispatcher();
    
    void appendToTouchDispatch(cocos2d::CCTouchDelegate* p_touchableObject);
    
#pragma mark 觸摸相關
    //開始
    bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    
    //移動
    void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    
    //結束
    void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    
    //點擊home鍵或其它方式引起的取消
    void ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    
    
public:
    //cocos2d::CCArray* m_touchDispatchTable;
    std::vector<cocos2d::CCTouchDelegate*> m_touchDispatchTable;
    int m_iIndex;//m_iIndex-1爲實際索引
};

#endif /* defined(__MythLeague__UpperLayer__) */

//
//  UpperLayer.cpp
//  MythLeague
//
//  Created by raochongtao on 13-6-26.
//
//

#include "UpperLayer.h"

using namespace cocos2d;

UpperLayer::UpperLayer(){
    
}
UpperLayer::~UpperLayer(){
    
    
}

bool UpperLayer::init(){
    bool l_bResult = true;
    do {
        if(!TouchLogicLayer::init()){
            l_bResult = false;
        }                
        
    } while (0);
    return l_bResult;
}

void UpperLayer::onEnter(){
    TouchLogicLayer::onEnter();
}
void UpperLayer::onExit(){
    TouchLogicLayer::onExit();
}

void UpperLayer::registerWithTouchDispatcher()
{
    cocos2d::CCDirector* pDirector = cocos2d::CCDirector::sharedDirector();
    pDirector->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority-1, true);
}

void UpperLayer::appendToTouchDispatch(CCTouchDelegate* p_touchableObject){
    //斷言,p_touchableLayer是CCLayer*類型, (可以是繼承)
    CCAssert(dynamic_cast<CCTouchDelegate*>(p_touchableObject) != NULL, "p_touchableLayer must be a layer");
    m_touchDispatchTable.push_back(p_touchableObject);
}

#pragma mark 觸摸相關
//開始
bool UpperLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
    //super
    TouchLogicLayer::ccTouchBegan(pTouch, pEvent);
    
    m_iIndex = Common_Empty;
    CCTouchDelegate* l_touchAble = NULL;
    int l_iIndex = 0;
    for (; l_iIndex<m_touchDispatchTable.size(); l_iIndex++) {
        l_touchAble = m_touchDispatchTable[l_iIndex];
        if (l_touchAble && l_touchAble->ccTouchBegan(pTouch, pEvent))
        {
            m_iIndex = l_iIndex;
            break;
        }
    }    
    return true;
}

//移動
void UpperLayer::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
    //super
    TouchLogicLayer::ccTouchMoved(pTouch, pEvent);
    
    if (m_iIndex >= 0) {
        CCTouchDelegate* l_touchAble = m_touchDispatchTable[m_iIndex];
        l_touchAble->ccTouchMoved(pTouch, pEvent);
    }
}

//結束
void UpperLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
    //super
    TouchLogicLayer::ccTouchEnded(pTouch, pEvent);
    
    if (m_iIndex >= 0) {
        CCTouchDelegate* l_touchAbleLayer = m_touchDispatchTable[m_iIndex];
        l_touchAbleLayer->ccTouchEnded(pTouch, pEvent);
    }
}

//點擊home鍵或其它方式引起的取消
void UpperLayer::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
    
}

所有的彈出層,只要繼承一下這個就可以,他的優點是事件分發由自己來控制,比較靈活

發佈了46 篇原創文章 · 獲贊 15 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章