from http://www.2cto.com/kf/201308/236359.html
注:下面这位同学对于cocos2d-x 2.x中的触摸机制分析简直可以说是清晰到家了。
重要补充: 下面这位同学说得还少了一点,至少我使用当前的COCOS2D-X 2.2.4中测试发现,注册任务不一定非要在registerWithTouchDispatcher方法中实现(当然,这个地方注册可以看作是标准位置吧)。我在init函数中注册也是可以的。当然是调试通过我才这样下结论的! |
在Cocos2d-x中提供两种触摸事件处理机制:CCStandardTouchDelegate和CCTargetedTouchDelegate。
一、如何使用
0、默认情况下CCLayer都是没有启动触摸事件的
所以需要在初始化函数中 this->setTouchEnabled(true); 启用触摸事件处理。
1、首先需要在 registerWithTouchDispatcher() 方法中注册处理触摸事件的机制。
[cpp]
void HelloWorld::registerWithTouchDispatcher()
{
//Standard Touch
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0);
//Targeted Touch
// CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}
void HelloWorld::registerWithTouchDispatcher()
{
//Standard Touch
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 0);
//Targeted Touch
// CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}
PS: CCLayer的默认registerWithTouchDispatcher实现是注册为CCStandardTouchDelegate, 另外,在调用的时候不能自己调用registerWithTouchDispatcher,而应该调用
this->setTouchEnabled(true);
注意:我们在使用触摸事件机制的时候进行了注册,那么显然在使用后,需要进行remove的处理吧,其实这部分的内容不需要我们手动处理,移除的操作会自动在OnExit时候执行,所以不需要我们去关心!
2、实现回调函数
在两种实现机制中都分别指定了处理触摸事件的回调函数,所以用户在注册了不同的处理机制后,就需要实现响应的回调函数。
(1)Standard Touch
在CCStandardTouchDelegate包含四个回调函数,分别如下:
CCStandardTouchDelegate 默认事件
virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent); 处理按下事件
virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent); 处理按下并移动事件
virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); 处理松开事件
virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent); 处理打断事件
①这些回调函数中的参数,接收到的touch触摸是CCSet类型,说明是多点的touch。那么就可以实现多点触摸的处理了。如果要想实现多点触摸,那么首先需要在
[cpp]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法中设置:
[cpp]
//设置多点触摸
[__glView setMultipleTouchEnabled:YES];
//设置多点触摸
[__glView setMultipleTouchEnabled:YES];
那么在回调函数中就可以进行多点触摸的处理了:
[cpp]
void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
CCLog("tap count = %d",pTouches->count());
for (CCSetIterator iterTouch = pTouches->begin(); iterTouch != pTouches->end(); iterTouch ++) {
CCTouch *pCurTouch = (CCTouch*)(*iterTouch);
CCPoint point = pCurTouch->getLocation();
CCLog("%f,%f",point.x,point.y);
}
}
void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
CCLog("tap count = %d",pTouches->count());
for (CCSetIterator iterTouch = pTouches->begin(); iterTouch != pTouches->end(); iterTouch ++) {
CCTouch *pCurTouch = (CCTouch*)(*iterTouch);
CCPoint point = pCurTouch->getLocation();
CCLog("%f,%f",point.x,point.y);
}
}
(2)Target Touch
CCTargetedTouchDelegate 包含下面四个回调函数:
CCTargetedTouchDelegate
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); 处理用户按下事件,true表示继续处理, 否则false.
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent); 处理按下并移动事件
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); 处理松开事件
virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); 处理打断事件
CCTargetedTouchDelegate 和 CCStandardTouchDelegate 有很大的区别。
第一,CCTargetedTouchDelegate 回调里的参数接收的不是Touch事件的集合(CCSet),而是单个的Touch事件,cocos2d-x会将多点触摸拆散成单个的Touch事件再进行回调。即事件参数不再是集合,而是一次只传入一个触摸点。
第二,用户必须实现ccTouchBegan 函数,且如果某个用户按下消息需要继续跟踪,则ccTouchBegin返回true, 否则,ccTouchMoved,ccTouchEnded等接口不会被调用到。即ccTouchBegan方法返回一个布尔值,表示声明是否要捕捉这个 触摸点,只有在此方法中捕捉到的触摸点才会继续引发其他3个事件,否则此触摸点的其他事件都会被忽略。
第三,注意到
[cpp]
void CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)
void CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)
在addTargetedDelegate方法中,前两个参数分别对应触摸接收对象和优先级,其中优先级是一个整型参数,值越低,则优先级越高,也就越早获得触摸事件。通常,为了获得较高的优先级,可以将其指定为负数。
其中的第三个参数较为有趣,表明了是否"吞噬"一个触摸,如果设置为true,一个触摸一旦被捕捉,那么所有优先级更低的接收对象都无法接收到触摸。即用 户在注册TargetTouchDelegate的时候可以设置bSwallowsTouches标识,若某个TargetTouchDelegate将 该标识设为true,且需要处理某个Touch事件(ccTouchBegan
返回true),则调到该Delegate之后cocos2d-x不会将Touch消息发送给其他的TargetTouchDelegate和StandardTouchDelegate。
例如:CCMenu就是一个会"吞噬"且优先级为-128的触摸接收器,由于它的优先级很高,所以菜单按钮总能获得触摸响应。
二、touch 事件分发顺序
cocos2d-x 首先派发事件给CCTargetedTouchDelegate, 再派发事件给CCStandardTouchDelegate。对于相同类型的TouchDelegate, 则是根据注册的优先级
来确定派发先后顺序。如果优先级也一样,则按照注册的顺序派发事件。