两种Cocos2d-x触摸事件:
1,我们已经见到了CCLayer处理触摸事件的方法。当我们开启CCLayer的TouchEnable属性后,层中的4个回调函数就会在接收到事件时被触发,我们把这类事件称作标准触摸(standard touch)事件,它的特点是任何层都会平等地接收全部触摸事件。
2,除此以外,Cocos2d-x还提供了另一种被称作带目标的触摸事件(targeted touch)机制。在带目标的触摸机制中,接收者并不平等,较早处理事件的接收者有权停止事件的分发,使它不再继续传递给其他接收者。换句话说,带目标的触摸事件并不一定会被广播给所有的接收者。通常,游戏的菜单按钮、摇杆按钮等元件常使用目标触摸事件,以保证触摸事件不对其他层产生不良影响。
标准触摸事件:
我们知道利用CCLayer可以方便地启用层上的标准触摸事件。实际上,并不是只有层才支持接收触摸事件,任何一个游戏元素都可以接受事件,只不过层中提供了现成的支持。下面我们将以层为例,来探究一下层是如何开启标准触摸事件的。
如果设置开启触摸,则会调用registerWithTouchDispatcher方法。而在registerWithTouchDispatcher方法中,我们调用了CCTouchDispatcher的addStandard- Delegate方法。在引擎中,CCTouchDispatcher负责触摸事件的分发处理,此处的addStan- dardDelegate方法会把当前对象注册到分发器中。被注册的对象必须实现CCStandardTouch- Delegate接口,当引擎从系统接收到触摸事件时,就会调用接口中对应的方法,触发触摸事件。
相比之下,关闭触摸则简单得多:只需要调用CCTouchDispatcher的removeDelegate方法即可。
因此可以总结,为了使一个对象接受标准触摸事件,主要有以下4个步骤。
1,需要此对象实现CCStandardTouchDelegate接口。
2,使用addStandardDelegate方法把自己注册给触摸事件分发器。
3,重载事件回调函数,处理触摸事件;
4,当不再需要接收触摸事件时,使用removeDelegate方法来注销触摸事件的接收。
注: 必须多点同时触摸看能不能出发,单点你是没办法出发的,在模拟器上就别想触发了。
带目标的触摸事件:
我们可以为任意对象添加标准触摸事件,然而如同前文所述,标准触摸事件中存在两个较为不便的地方,具体如下所示:
1,只要事件分发器接收到用户的触摸事件,就会分发给所有的订阅者,因此常常会出现按下按钮时,触摸事件穿透按钮分发给后面的层这种尴尬的情况。
2,当系统存在多个触摸点时,标准触摸事件会把所有触摸点都传递给回调函数,然而在许多情况下每个触摸点之间是独立的,屏幕上是否存在其他触摸点我们并不不关心,因此我们不必为了处理多个触摸事件手动遍历一遍触摸点。
3,为此,Cocos2d-x为我们提供了一个简化的解决方案:带目标的触摸事件。与标准触摸事件类似,我们也需要首先使接受事件的对象实现一个接口CCTargetedTouchDelegate,然后把对象注册到触摸分发器中,最后当不再需要接受触摸事件时注销自身。
触摸中的陷阱
触摸处理机制的规则并不复杂,但是存在一些容易让人产生误解的陷阱。
第一个陷阱是接收触摸的对象并不一定正显示在屏幕上。触摸分发器和引擎中的绘图是相互独立的,所以并不关心触摸代理是否处于屏幕上。因此,在实际使用中,应该在不需要的时候及时从分发器中移除触摸代理,尤其是自定义的触摸对象。而CCLayer也仅仅会在切换场景时将自己从分发器中移除,所以同场景内手动切换CCLayer的时候,也需要注意禁用触摸来从分发器移除自己。
另一个陷阱出自CCTargetedTouchDelegate。尽管每次只传入一个触摸点,也只有在开始阶段被声明过的触摸点后续才会传入,但是这并不意味着只会接收一个触摸点:只要被声明过的触摸点都会传入,而且可能是乱序的。因此,一个良好的习惯是,如果使用CCTargeted- TouchDelegate,那么只声明一个触摸,针对一个触摸作处理即可。