多触点与触屏事件详解单一监听、事件分发

李华明Himi原创,转载务必在明显处注明:
转载自 【黑米GameDev街区】原文链接: http://www.himigame.com/iphone-cocos2d/450.html


-----------------------------------本章补充开始!----------------------------------

本篇对于多触点和触屏事件已经做了一个详细的说明,但是有一点忽略了,就是开启多触点的支持!步骤如下:

首先进入AppDelegate.m 类中,

  1. <strong>-(void)applicationDidFinishLaunching:(UIApplication*)application{}</strong>

在上面这个方法中添加如下一句开启多触点支持的代码:

  1. <strong>//支持多触点
  2. [viewController.viewsetMultipleTouchEnabled:YES];</strong>

其他类设置多触点:

[[[CCDirector sharedDirector]openGLView]setMultipleTouchEnabled:YES];

--------------------------本章补充完毕------------------------------------------------------------------------------


最近几天一直在啃cocos2d,消化了不少东西,基本可以有些把握下手写公司的游戏了;那么今天就把一些重点的拿出来分享下经验,给新童鞋们作为参考;

这篇就来详细介绍下cocos2d对用户触屏的监听事件进行下分析(cocos2d有很多详细的文章和教程,我这里只是出于自己的理解来说)

进入正题:从整体cocos2d对触屏的事件监听可以分为两种:

1.单一监听,所谓单一监听其实是跟cocos2d引擎框架有关,因为在cocos2d中每个游戏界面都可以使用一个CCLayout完成,那么当一个CCLayout在屏幕显示出来后,想要监听用户的按键事件,一般都会使用以下形式来进行监听:(注意:这里是CCLayout类进行监听的方式)

首先开启监听:

  1. self.isTouchEnabled=YES;
然后重写监听函数即可:
  1. //监听首次触发事件
  2. -(void)ccTouchesBegan:(NSSet*)toucheswithEvent:(UIEvent*)event
  3. {
  4. }
  5. //触摸事件-当手指在屏幕上进行移动
  6. -(void)ccTouchesMoved:(NSSet*)toucheswithEvent:(UIEvent*)event
  7. {
  8. }
  9. //触摸事件-当手指从屏幕抬起时调用的方法
  10. -(void)ccTouchesEnded:(NSSet*)toucheswithEvent:(UIEvent*)event
  11. {
  12. }
此种监听狠eazy,但是要注意这里是对CCLayout类进行的监听方式;


2.监听分发; 刚才说了,游戏的每个界面可能都是一个CCLayout,但是如果我想让一个CCSprite精灵主角单独进行监听,或者说在CCLayout有很多个精灵我想单独监听其中的一种的时候,这时候就需要使用监听分发的形式了;

假设我们自定义了一个类XX继承CCSprite,还有一个YY类也继承CCSprite,而且XX类型与YY类的实例都存在于一个Layout上,那么我想对XX与YY类型分别单独监听的话;首先我们先让当前继承的CCSprite类的XX于YY类都使用 <CCTargetedTouchDelegate>协议;

(CCSprite中没有 self.isTouchEnabled=YES; 这个函数,别直接写这个哦~)

代码如下:

  1. @interfaceXX:CCSprite<CCTargetedTouchDelegate>{
  2. }

然后在当前实现类中重写一个函数如下:
  1. -(void)registerWithTouchDispatcher
  2. {
  3. [[CCTouchDispatchersharedDispatcher]addTargetedDelegate:selfpriority:0swallowsTouches:YES];
  4. }


或者将注册的这句代码,放在重写的onEnter函数中也可;


(此函数是注册监听,如果里面什么都不写,则当前不会相应任何触屏事件;)

重写触摸的各事件函数,如下:

  1. //监听首次触发事件
  2. -(BOOL)ccTouchBegan:(UITouch*)touchwithEvent:(UIEvent*)event
  3. {
  4. returnNO;
  5. }
  6. //监听移动事件
  7. -(void)ccTouchMoved:(UITouch*)touchwithEvent:(UIEvent*)event
  8. {
  9. }
  10. //监听离开事件
  11. -(void)ccTouchEnded:(UITouch*)touchwithEvent:(UIEvent*)event
  12. {
  13. }

大家可以看到,此种监听方式除了各种监听函数与第一种类似之外,在 ccTouchBegan的函数有个返回类型-布尔值;那么其作用下面详细介绍;如果XX与YY类都实现了第二种监听方式的话,那么当用户触屏后,(当前用户触发的是XX与YY类实例所在的CCLayout)首先会进入XX或者YY的其中的ccTouchBegan函数中,这里假设首先进入了XX类中,那么XX类中的ccTouchBegan将会被响应,如果return true;表示不再将用户触屏的消息传递给YY类中进行响应,也就是说不再响应YY类中的ccTouchBegan函数,那么如果 return false;则会将当前触屏信息传递给其他注册过的类型中;

一句话概括:return 的值,如果是真则表明用户触摸事件已经被处理,其他不会再去进行监听;如果为假,则会继续交给其他注册过的类型中进行处理;


那么第二种监听的方式比较常用,这样便于处理,那么至于注册,一般都是放在onEnter函数中;onEnter函数是每个CCScene之间切换会被响应的函数,相当于是CCScene的生命周期函数,具体调用顺序如下:

  1. //使用[CCDirectorreplaceScene:XX],替换场景时,会调用以下3个方法
  2. //调用顺序依次为:
  3. //1.othterScene的+(id)Scene——>
  4. //2.otherScene的init——>
  5. //3.otherScene的onEnter——>
  6. //4.运行过渡效果
  7. //5.当前Scene的onExit函数——>
  8. //6.otherLayout的onEnterTransitionDidFinish()
  9. //7.当前Scene的dealoc函数
  10. -(void)onEnter{
  11. //调用其他Scene的init方法以后会调用此方法
  12. //如果使用了CCTransitionScene,本方法将在过渡效果开始后调用
  13. //(如果不调用superonEnter新场景可能对触摸和加速计无发应)
  14. [superonEnter];
  15. }
  16. -(void)onEnterTransitionDidFinish{
  17. //调用onEnter后会调用此函数
  18. //如果使用了CCTransitionScene,将会在过渡效果完成时调用此方法
  19. [superonEnterTransitionDidFinish];
  20. }
  21. -(void)onExit{
  22. //在调用dealloc之前会调用此函数;
  23. //如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法
  24. //(如果不调用superonExit,当前场景可能不会从内存中释放)
  25. [superonExit];
  26. }

那么大概介绍了监听事件后,那么触屏中最关心的就应该是多触点啦;
  1. //-----获取多点触摸
  2. NSSet*allTouches=[eventallTouches];
  3. UITouch*touchOne=[[allTouchesallObjects]objectAtIndex:0];
  4. UITouch*touchTwo=[[allTouchesallObjects]objectAtIndex:1];
  5. //...类推

获取多点狠简单,那么下面再将基本常用到的几个判断写下:

1-判断用户单击还是双击(针对一个触点)

  1. if([allTouchescount]==1){
  2. UITouch*touchOne=[[allTouchesallObjects]objectAtIndex:0];
  3. switch([touchOnetapCount]){
  4. case1:
  5. //单击
  6. CCLOG(@"%@",@"单击");
  7. break;
  8. case2:
  9. //双击
  10. CCLOG(@"%@",@"双击");
  11. break;
  12. }
  13. }

1-判断用户两个触点之间是合拢还是分开(针对两个触点)

  1. <prename="code"class="cpp">if([allTouchescount]==2){
  2. //适当修改处理,不能同时取,否则肯定一样的啦(可以一个在began一个在end)
  3. UITouch*touchOne=[[allTouchesallObjects]objectAtIndex:0];
  4. UITouch*touchTwo=[[allTouchesallObjects]objectAtIndex:1];
  5. CGFloat*disFirst=[selfdistance:[touchOnelocationInView:[selfview]]
  6. todistance:[touchTwolocationInView:[selfview]]];
  7. UITouch*touchOne=[[allTouchesallObjects]objectAtIndex:0];
  8. UITouch*touchTwo=[[allTouchesallObjects]objectAtIndex:1];
  9. CGFloat*disFinal=[selfdistance:[touchOnelocationInView:[selfview]]
  10. todistance:[touchTwolocationInView:[selfview]]];
  11. if(disFirst>disFinal){
  12. CCLOG(@"%@",@"合拢");
  13. }else{
  14. CCLOG(@"%@",@"分开");
  15. }
  16. }</pre><br><pre></pre><p></p><pre></pre><p></p><pclass="p1">这里我就粗略的写在一起,判定两个触点是否合拢其实就是用户刚触屏时记录两点之间的距离记做disFirst,然后在两个触点离开屏幕(或者移动事件中)的时候计算</p><pclass="p1">当前的两个触点的距离disFinal,那么最后根据disFirst与disFinal距离关系就能知道是合拢还是分开;</p><pclass="p1">(CCLOG是cocos2d封装的打印方法,此种打印在编译发布正式游戏程序的时候是不会编译到程序中的,但是NSLOG会一直存在!要注意!)</p><pclass="p1"></p><pclass="p1">最后给出两个函数,用于计算不同方式监听的函数中获取(转换)坐标的,因为cocos2d是openGL进行搭建的框架,所以需要坐标转换;</p><pclass="p1"></p><prename="code"class="cpp">+(CGPoint)locationFromTouches:(NSSet*)touches
  17. {
  18. return[selflocationFromTouch:[touchesanyObject]];
  19. }
  20. +(CGPoint)locationFromTouch:(UITouch*)touch
  21. {
  22. CGPointtouchLocation=[touchlocationInView:[touchview]];
  23. return[[CCDirectorsharedDirector]convertToGL:touchLocation];
  24. }</pre><br>两个方法一看就能看出区别,一个是UITouch的,一个是NSSet,一个是单一监听,一个是分发监听;<p></p><pclass="p1">ok,本章就到这里~~~(下周进入封闭开发了,吃睡都在公司了,咳咳,带上我的多啦a梦的小裤衩,娃哈哈~)</p><pclass="p1"><br></p><pclass="p1"><br></p><pclass="p1"><br></p><pclass="p1"><br></p><pclass="p1"><br></p><br><pre></pre><pre></pre><pre></pre>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结