cocos2d-x touch

本文详细介绍了Cocos2d-x中触摸事件的处理机制,包括两种不同的处理方式CCStandardTouchDelegate和CCTargetedTouchDelegate,以及触摸事件的派发顺序和Cocos2d-x内部实现原理。此外,还提供了屏蔽场景触摸事件的方法,适用于暂停CCScene运行时防止意外触发动作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.csdn.net/yuanhong2910/article/details/7004411

http://www.cocos2dev.com/?p=157

cocos2d-x Touch事件处理机制

cocos2d-x 提供了一种简单而又灵活的触摸事件派发机制,由于它实现得太灵活,导致一个新手在处理一些复杂的场景时可能会比较难掌握。

一. 如何使用

cocos2d-x提供了两种触摸事件处理机制, 分别是CCStandardTouchDelegate 和 CCTargetedTouchDelegate。

CCStandardTouchDelegate包含四个回调函数,分别如下:

     virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)   处理用户按下事件

     virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)   处理Touch Move 事件

    virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)    处理用户放开事件

    virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent)  处理Touch被打断事件,如来电话了。

在用户注册了一个CCStandardTouchDelegate之后, 所有的触摸事件都会回调到用户自己定义的CCStandardTouchDelegate。


CCTargetedTouchDelegate 包含下面四个回调函数:

 virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)       处理用户按下事件,若用户需要继续处理该按下对应的后续事件,则return true, 否则,return false.

 virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)       处理Touch Move 事件

virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)        处理用户放开事件

 virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent)   处理Touch被打断事件.

CCTargetedTouchDelegate 和 CCStandardTouchDelegate 有很大的区别。

第一,CCTargetedTouchDelegate 回调里的参数接收的不是Touch事件及集合(CCSet),而是单个的Touch事件,cocos2d-x会将多点触摸拆散成单个的Touch事件再进行回调。

第二,用户必须实现ccTouchBegan 函数,且如果某个用户按下消息需要继续跟踪,则ccTouchBegin返回true, 否则,ccTouchMove等接口不会被调用到。

第三,用户在注册TargetTouchDelegate的时候可以设置bSwallowsTouches标识,若某个TargetTouchDelegate将该标识设为true,且需要处理某个Touch事件(ccTouchBegan返回true),则调到该Delegate之后cocos2d-x不会将Touch消息发送给其他的TargetTouchDelegate和StandardTouchDelegate。

PS: CCLayer的默认registerWithTouchDispatcher实现是注册为CCStandardTouchDelegate, 另外,在调用的时候不能自己调用registerWithTouchDispatcher,而应该调用setIsTouchEnable(true/false).

二. Touch 事件派发的顺序

cocos2d-x 首先派发事件给CCTargetedTouchDelegate, 再派发事件给CCStandardTouchDelegate。对于相同类型的TouchDelegate, 则是根据注册的优先级来确定派发先后顺序。如果优先级也一样,则按照注册的顺序派发事件。

三. cocos2d-x实现原理

cocos2d-x 内部处理Touch事件类图如下所示:

如上图所示,CCTouchDispatcher是管理cocos2d-x中所有Touch事件派发的类,CCTouchDispatcher中包含了两个CCTouchHandler的列表,分别存储StandardTouchHandler和 TargetedTouchHandler。同时,CCTouchDispatcher实现了EGLTouchDelegate去接收窗口的触摸消息,当其接收到窗口触摸消息时,调用touches接口将触摸事件传递给TouchDelegate。

当用户调用addStandardDelegate时,CCTouchDispatcher会用用户传入的CCTouchDelegate指针创建一个CCStandardTouchHandler对象并且插入StandardTouchHandler列表中。addTargetedDelegate的实现和addStandardDelegate类似。


cocos2d-x 屏蔽场景的Touch事件


cocos2d-x有个问题,即使暂停CCScene运行,触摸仍然有效,有些菜单和按钮仍然会被触发。

所以有的时候我们要手动屏蔽触摸,尤其是在弹出计费画面的,或者使用一些本平台自带控件的时候。

做法有几种:

第一种方案是:每一个继承自CCLayer的类都可以关闭触摸,使用这个函数

1 setIsTouchEnabled(false);

在暂停sence时,我们只需要关闭那些主要的CCLayer即可,也就是当前CCScene的主CCLayer和相关的CCMenu等。

但这种方法,有时候会造成莫名其妙的crash。调试发现,如果在同一个frame的同一个函数中,先关闭再恢复触摸,就可能造成crash。crash的原因是引擎在派发触摸事件时,发现响应对象的列表为空,直接触发断言。

第二种方案是:写一个CCLayer,把所有优先级调至最高,并直接覆盖到当前CCSence主CCLayer上。

经过试验,这种方式非常简单有效,重用性也很高。

01 class NoTouchLayer : public cocos2d::CCLayer{
02 public:
03  // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
04  virtual bool init();
05  
06 // implement the "static node()" method manually
07 LAYER_NODE_FUNC(NoTouchLayer);
08  
09 virtualvoid registerWithTouchDispatcher();
10  
11 virtualbool ccTouchBegan (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
12 virtualvoid ccTouchMoved (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
13 virtualvoid ccTouchEnded (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
14  
15 };

实现方法

01 bool NoTouchLayer::init(){
02 if (!CCLayer::init() )
03 {
04 return false;
05 }
06  
07 setIsTouchEnabled(true);
08  
09 return true;
10 }
11  
12 void NoTouchLayer::registerWithTouchDispatcher(){
13 CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, numeric_limits <int> ::min() , true);
14  
15 //使用int最小值做最高优先级,并且吞掉事件true
16  
17 CCLayer::registerWithTouchDispatcher();
18 }
19  
20 bool NoTouchLayer::ccTouchBegan (CCTouch *pTouch, CCEvent *pEvent){
21 return true;
22 }
23  
24 void NoTouchLayer::ccTouchMoved (CCTouch *pTouch, CCEvent *pEvent){  }
25  
26 void NoTouchLayer::ccTouchEnded (CCTouch *pTouch, CCEvent *pEvent){  }

这个类的使用也很简单,直接addChild,removeChild即可。注意清理,注意addChild的时候要给一个足够大的z轴深度值。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值