轉載請註明出處 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){
}
所有的彈出層,只要繼承一下這個就可以,他的優點是事件分發由自己來控制,比較靈活