转载请注明出处 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){
}
所有的弹出层,只要继承一下这个就可以,他的优点是事件分发由自己来控制,比较灵活