cocos2d-x添加触摸层阻止后端事件

2015年01月14日 13:38 0 点赞 0 评论 更新于 2025-11-21 14:22

在cocos2d-x开发中,有时我们需要弹出一个层,屏蔽后面的事件,同时在当前层添加一些按钮供用户进行不同的选择,比如“确定”或“取消”。下面我们来详细探讨如何实现这一功能。

问题分析

在cocos2d-x中,优先级小的对象会先响应触摸事件。通常情况下,我们可以通过设置新添加的CCLayer层的优先级来控制触摸事件的响应顺序。然而,由于CCMenu的优先级较高,可能会透过我们添加的触摸层,响应之前绑定的Button事件。如果将此触摸层的优先级设置得比Button低,又会导致在这层添加的Button按钮的触摸事件无法触发,使得本层应该响应的触摸事件也无法正常响应,达不到我们理想的效果。

解决方案

自cocos2d-x 2.0版本后,新增了CCControlButton,其优先级为0,比默认的Button优先级高。因此,我们可以在当前层添加CCControlButton,并将弹出层的Layer优先级设置为小于0的值。这样,在弹出层添加Menu就能够正常响应触摸事件,同时也不会影响后面的事件。当然,由于CCControlButton的优先级可以自动设置,我们也可以将弹出层的优先级设置为 -128(或更小),然后将CCControlButton的优先级设置得更小。

代码实现

1. 创建触摸层

BlockTouchLayer *block = BlockTouchLayer::create();
this->addChild(block);

2. BlockTouchLayer的声明文件

#ifndef __test__BlockTouchLayer__
#define __test__BlockTouchLayer__

#include <iostream>
#include "cocos2d.h"
#include "cocos-ext.h"

using namespace cocos2d;

class BlockTouchLayer : public CCLayerColor
{
public:
virtual bool init();
void initData();
virtual void registerWithTouchDispatcher();
// 重写触摸事件,阻止后端事件响应
virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
virtual void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
void callBack(CCObject *pSender, CCControlEvent event);
CREATE_FUNC(BlockTouchLayer);
};

#endif

3. BlockTouchLayer的具体实现文件

#include "BlockTouchLayer.h"
USING_NS_CC_EXT;

bool BlockTouchLayer::init()
{
ccColor4B color = {100, 0, 0, 125};
// 设置面板颜色及透明度
if (!CCLayerColor::initWithColor(color))
{
return false;
}
initData();
setTouchEnabled(true);
// 开启触摸事件
return true;
}

void BlockTouchLayer::initData()
{
CCSize winsize = CCDirector::sharedDirector()->getWinSize();
CCSprite *sp = CCSprite::create("Icon.png");
this->addChild(sp);
sp->setPosition(ccp(winsize.width / 2, winsize.height / 2));

CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache();
cache->addSpriteFramesWithFile("load.plist", "load.png");

CCSprite *sprite1 = CCSprite::createWithSpriteFrameName("loading1.png");
sprite1->setPosition(ccp(winsize.width / 2, winsize.height / 2));

CCSpriteBatchNode *batchNode = CCSpriteBatchNode::create("load.png");
batchNode->addChild(sprite1);
this->addChild(batchNode);
// 可以起到一定的优化作用,最好不要直接添加精灵

CCArray *spriteArray = CCArray::create();
char str[100] = {0};
for (int i = 1; i <= 14; i++)
{
sprintf(str, "loading%d.png", i);
CCSpriteFrame *frame = cache->spriteFrameByName(str);
spriteArray->addObject(frame);
}

CCAnimation *animation = CCAnimation::createWithSpriteFrames(spriteArray, 0.5);
sprite1->runAction(CCRepeatForever::create(CCAnimate::create(animation)));

cocos2d::extension::CCScale9Sprite *sprite9 = cocos2d::extension::CCScale9Sprite::create("btn_blackblue.png");
CCLabelTTF *label = CCLabelTTF::create("click me", "", 22);
cocos2d::extension::CCControlButton *controlButton = cocos2d::extension::CCControlButton::create(label, sprite9);
controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(BlockTouchLayer::callBack), cocos2d::extension::CCControlEventTouchDown);
this->addChild(controlButton);
controlButton->setPosition(ccp(winsize.width / 3, winsize.height / 2));
controlButton->setTouchPriority(-200);
// 设置CCControlButton的优先级
// controlButton->setZoomOnTouchDown(true);
}

void BlockTouchLayer::callBack(cocos2d::CCObject *pSender, CCControlEvent event)
{
// CCNotificationCenter::sharedNotificationCenter()->postNotification("click", this);
BlockTouchLayer *tmplayer = (BlockTouchLayer *)((CCMenu *)(pSender))->getParent();
tmplayer->removeFromParentAndCleanup(true);
// 点击按钮后,移除弹出的面板
}

void BlockTouchLayer::registerWithTouchDispatcher()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, true);
// 注册并设置当前面板触摸的优先级
}

bool BlockTouchLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
return true;
// 吞噬掉后面的响应
}

void BlockTouchLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
}

void BlockTouchLayer::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
}

最终实现效果

第一张图片点击右下角的退出按钮,没有反应;点击“click me”按钮,取消当前层显示原来的“hello world”层,此时退出按钮有效。

通过以上步骤,我们成功在cocos2d-x中添加了触摸层,并阻止了后端事件的响应,同时保证了当前层按钮的正常交互。

作者信息

feifeila

feifeila

共发布了 3994 篇文章