单一监听和分发监听.docx_第1页
单一监听和分发监听.docx_第2页
单一监听和分发监听.docx_第3页
单一监听和分发监听.docx_第4页
单一监听和分发监听.docx_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

单一监听和分发监听这篇就来详细介绍下cocos2d对用户触屏的监听事件进行下分析(cocos2d有很多详细的文章和教程,我这里只是出于自己的理解来说)进入正题:从整体cocos2d对触屏的事件监听可以分为两种:1.单一监听,所谓单一监听其实是跟cocos2d引擎框架有关,因为在cocos2d中每个游戏界面都可以使用一个CCLayout完成,那么当一个CCLayout在屏幕显示出来后,想要监听用户的按键事件,一般都会使用以下形式来进行监听:(注意:这里是CCLayout类进行监听的方式)首先开启监听:1self.isTouchEnabled=YES;然后重写监听函数即可:1234567891011121314 /监听首次触发事件 - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event /触摸事件 - 当手指在屏幕上进行移动 - (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event /触摸事件 - 当手指从屏幕抬起时调用的方法 -(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 此种监听狠eazy,但是要注意这里是对CCLayout类进行的监听方式;2.监听分发; 刚才说了,游戏的每个界面可能都是一个CCLayout,但是如果我想让一个CCSprite精灵主角单独进行监听,或者说在CCLayout有很多个精灵我想单独监听其中的一种的时候,这时候就需要使用监听分发的形式了;假设我们自定义了一个类XX继承CCSprite,还有一个YY类也继承CCSprite,而且XX类型与YY类的实例都存在于一个Layout上,那么我想对XX与YY类型分别单独监听的话;首先我们先让当前继承的CCSprite类的XX于YY类都使用 协议;(CCSprite中没有 self.isTouchEnabled=YES; 这个函数,别直接写这个哦)代码如下:123 interface XX : CCSprite 然后在当前实现类中重写一个函数如下:1234 -(void) registerWithTouchDispatcher CCTouchDispatcher sharedDispatcher addTargetedDelegate:self priority:0 swallowsTouches:YES; (此函数是注册监听,如果里面什么都不写,则当前不会相应任何触屏事件;)重写触摸的各事件函数,如下:1234567891011121314 /监听首次触发事件 - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event return NO; /监听移动事件 - (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event /监听离开事件 - (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 大家可以看到,此种监听方式除了各种监听函数与第一种类似之外,在 ccTouchBegan的函数有个返回类型布尔值;那么其作用下面详细介绍;如果XX与YY类都实现了第二种监听方式的话,那么当用户触屏后,(当前用户触发的是XX与YY类实例所在的CCLayout)首先会进入XX或者YY的其中的ccTouchBegan函数中,这里假设首先进入了XX类中,那么XX类中的ccTouchBegan将会被响应,如果return true;表示不再将用户触屏的消息传递给YY类中进行响应,也就是说不再响应YY类中的ccTouchBegan函数,那么如果 return false;则会将当前触屏信息传递给其他注册过的类型中;一句话概括:return 的值,如果是真则表明用户触摸事件已经被处理,其他不会再去进行监听;如果为假,则会继续交给其他注册过的类型中进行处理;那么第二种监听的方式比较常用,这样便于处理,那么至于注册,一般都是放在 onEnter函数中;onEnter函数是每个CCScene之间切换会被响应的函数,相当于是CCScene的生命周期函数,具体调用顺序如下:1234567891011121314151617181920212223242526 /使用CCDirector replaceScene:XX,替换场景时,会调用以下3个方法 /调用顺序依次为: /1.othterScene的+(id)Scene> /2.otherScene的init> /3.otherScene的onEnter> /4.运行过渡效果 /5.当前Scene的onExit函数> /6.otherLayout的onEnterTransitionDidFinish() /7.当前Scene的dealoc函数 -(void) onEnter /调用其他Scene的init方法以后会调用此方法 /如果使用了CCTransitionScene,本方法将在过渡效果开始后调用 /(如果不调用super onEnter新场景可能对触摸和加速计无发应) super onEnter; -(void) onEnterTransitionDidFinish /调用onEnter后会调用此函数 /如果使用了CCTransitionScene,将会在过渡效果完成时调用此方法 super onEnterTransitionDidFinish; -(void)onExit /在调用dealloc之前会调用此函数; /如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法 /(如果不调用super onExit,当前场景可能不会从内存中释放) super onExit; 那么大概介绍了监听事件后,那么触屏中最关心的就应该是多触点啦;12345 /-获取多点触摸 NSSet *allTouches = event allTouches; UITouch *touchOne = allTouches allObjectsobjectAtIndex:0; UITouch *touchTwo = allTouches allObjectsobjectAtIndex:1; /.类推获取多点狠简单,那么下面再将基本常用到的几个判断写下:1判断用户单击还是双击(针对一个触点)1if(allTouches count=1) UITouch *touchOne = allTouches allObjectsobjectAtIndex:0; switch (touchOne tapCount) case 1: /单击 CCLOG(%,单击); break; case 2: /双击 CCLOG(%,双击); break; 1判断用户两个触点之间是合拢还是分开(针对两个触点)1if(allTouches count=2) /适当修改处理,不能同时取,否则肯定一样的啦(可以一个在began 一个在end) UITouch *touchOne = allTouches allObjectsobjectAtIndex:0; UITouch *touchTwo = allTouches allObjectsobjectAtIndex:1; CGFloat *disFirst =self distance:touchOne locationInView:self view todistance:touchTwo locationInView:self view; UITouch *touchOne = allTouches allObjectsobjectAtIndex:0; UITouch *touchTwo = allTouches allObjectsobjectAtIndex:1; CGFloat *disFinal =self distance:touchOne locationInView:self view todistance:touchTwo locationInView:self view; if (disFirstdisFinal) CCLOG(%,合拢); else CCLOG(%,分开); 这里我就粗略的写在一起,判定两个触点是否合拢其实就是用户刚触屏时记录两点之间的距离记做disFirst,然后在两个触点离开屏幕(或者移动事件中)的时候计算当前的两个触点的距离disFinal,那么最后根据disFirst与disFinal距离关系就能知道是合拢还是分开;(CCLOG 是cocos2d封装的打印方法,此种打印在编译发布正式游戏程序的时候是不会编译到程序中的,但是NSLOG会一直存在!要注意!)最后给出两个函数,用于计算不同方式监听的函数中获取(转换)坐标的,因为cocos2d是openGL进行搭建的框架,所以需要坐标转换;123456789 +(CGPoint) locationFromTouches:(NSSet*)touches return self locationFromTouch:touches anyObject; +(CGPoint) locationFromTouch:(UITouch*)touch CGPoint touchLocation = touch locationInView: touch view; return CCDirector sharedDirector convertToGL:touchLocation; 两个方法一看就能看出区别,一个是UITouch的,一个是NSSet,一个是单一监听,一个是分发监听;Cocos2d中各种坐标位置关系 接触Cocos2D有段时间了,今天特意研究了下Cocos2D坐标系中各种位置关系,anchor属性,CCNode坐标和地图坐标转换。 先看一段代码:cpp view plaincopyprint?1. -(id)init2. 3. /alwayscallsuperinit 4. /Applerecommendstore-assignselfwiththesuperreturnvalue 5. if(self=superinit)6. CCTMXTiledMap*gameWorld=CCTMXTiledMaptiledMapWithTMXFile:PositionText.tmx;7. selfaddChild:gameWorld;8. CGSizewinSize=CCDirectorsharedDirectorwinSize;9. CCLOG(gameWorld.mapSize.width:%.2fgameWorld.mapSize.height:%.2f,gameWorld.mapSize.width,gameWorld.mapSize.height);10. CCLOG(gameWorld.tileSize.width:%.2fgameWorld.tileSize.height:%.2f,gameWorld.tileSize.width,gameWorld.tileSize.height);11. CCLOG(winSize.width:%.2fwinSize.height:%.2f,winSize.width,winSize.height);12. 13. CCSprite*pointSprite=CCSpritespriteWithFile:point.png;14. gameWorldaddChild:pointSpritez:2tag:1;15. pointSprite.position=ccp(20,20);16. pointSprite.anchorPoint=ccp(0.5,0.5);17. 18. 19. CCSprite*rectSprite=CCSpritespriteWithFile:myrect.png;20. gameWorldaddChild:rectSpritez:1tag:1;21. rectSprite.position=ccp(20,20);22. rectSprite.anchorPoint=ccp(0.5,0.5);23. 24. returnself;25. 1、加载地图:cpp view plaincopyprint?1. CCTMXTiledMap*gameWorld=CCTMXTiledMaptiledMapWithTMXFile:PositionText.tmx;2、获取手机屏幕大小(320,480) cpp view plaincopyprint?1. CGSizewinSize=CCDirectorsharedDirectorwinSize;3、地图格子数: cpp view plaincopyprint?1. gameWorld.mapSize(10,10)4、地图格子大小: cpp view plaincopyprint?1. gameWorld.tileSize(20,20)5、整个地图大小: gameWorld.mapSize * gameWorld.tileSize; 当然这里所说的是地图格子是个正方形,非正方形也容易啦。6、anchor属性 1) 添加一个精灵,这个精灵是个像素为1*1的红色图片,设置坐标为20,20,即在地图的第一个格子的右上角,设置anchorPoint为(0.5, 0.5) 2) 再添加一个精灵,这个精灵是个像素为20*20的蓝色图片,设置坐标为20,20,即在地图的第一个格子的右上角,同样设置anchorPoint为(0.5, 0.5) 运行效果是矩形精灵的中心和在点精灵的位置,即矩形精灵的锚点为第一个格子的右上角(20,20)坐标 处 去掉两个精灵的anchorPoint属性 运行效果和上面相同 设置rectSprite的anchorPoint为ccp(0,0) 运行效果是矩形精灵的左下角与点精灵重合。 设置rectSprite的anchorPoint为ccp(1,1) 运行效果是矩形精灵的右上角与点精灵重合。 同理设置ccp(0.5, 1) , ccp(1, 0.5)等 由上面可以得出: 1)anchorPoint属性默认为ccp(0.5, 0.5) 2)当设置(0,0)时是以左下角为锚点 3)当设置(1, 1)时是以右上角角为锚点 4)由此可以自己推论到底该把锚点设置在哪里 Cocos2D使用的是OpenGL坐标系 OpenGL坐标系:原点在左下角, X轴向右,Y轴向上 IPhone屏幕坐标系:原点在左上角,X轴向右,Y轴向下 很简单的判断方法:由于Cocos2D的坐标系的原点在左下角。所以精灵内部坐标原点也是左下角,即当anchorPoint为(0, 0)时即以左下角为锚点,为(1,1)时就以右上角为锚点,当然(0.5, 0.5)就是以精灵中心为锚点了。由此可以推算出-2,-3. 2, 3. 等值时精灵锚点坐标。7、坐标转换 cpp view plaincopyprint?1. -(id)init2. 3. /alwayscallsuperinit 4. /Applerecommendstore-assignselfwiththesuperreturnvalue 5. if(self=superinit)6. CCTMXTiledMap*gameWorld=CCTMXTiledMaptiledMapWithTMXFile:PositionText.tmx;7. selfaddChild:gameWorld;8. CGSizewinSize=CCDirectorsharedDirectorwinSize;9. CCLOG(gameWorld.mapSize.width:%.2fgameWorld.mapSize.height:%.2f,gameWorld.mapSize.width,gameWorld.mapSize.height);10. CCLOG(gameWorld.tileSize.width:%.2fgameWorld.tileSize.height:%.2f,gameWorld.tileSize.width,gameWorld.tileSize.height);11. CCLOG(winSize.width:%.2fwinSize.height:%.2f,winSize.width,winSize.height);12. 13. CCSprite*pointSprite=CCSpritespriteWithFile:point.png;14. gameWorldaddChild:pointSpritez:2tag:1;15. pointSprite.position=ccp(20,20);16. /pointSprite.anchorPoint=ccp(0.5,0.5); 17. 18. 19. CCSprite*rectSprite=CCSpritespriteWithFile:myrect.png;20. gameWorldaddChild:rectSpritez:1tag:1;21. rectSprite.position=ccp(40,40);22. rectSprite.anchorPoint=ccp(2,2);23. 24. selfsetIsTouchEnabled:YES;25. 26. returnself;27. 28. 29. -(void)registerWithTouchDispatcher30. CCTouchDispatchersharedDispatcheraddTargetedDelegate:selfpriority:INT_MIN+1swallowsTouches:YES;31. 32. 33. -(BOOL)ccTouchBegan:(UITouch*)touchwithEvent:(UIEvent*)event34. CGPointpoint=touchlocationInView:touchview;35. CCLOG(ScreencoordX:%.2fcoordY:%.2f,point.x,point.y);36. 37. point=CCDirectorsharedDirectorconvertToGL:point;38. CCLOG(OpenGLcoordX:%.2fcoordY:%.2f,point.x,point.y);39. 40. point=selfconvertToNodeSpace:point;41. CCLOG(CCNode1coordX:%.2fcoordY:%.2f,point.x,point.y);42. 43. point=selfconvertTouchToNodeSpace:touch;44. CCLOG(CCNode2coordX:%.2fcoordY:%.2f,point.x,point.y);45. 46. point=CCDirectorsharedDirectorconvertToUI:point;47. CCLOG(UIViewcoordX:%.2fcoordY:%.2f,point.x,point.y);48. 49. point=rectSpriteconvertTouchToNodeSpaceAR:touch;50. CCLOG(TouchARcoordX:%.2fcoordY:%.2f,point.x,point.y);51. returnYES;CCNode52. 53. 54. -(void)ccTouchMoved:(UITouch*)touchwithEvent:(UIEvent*)event55. 56. 57. 58. -(void)ccTouchEnded:(UITouch*)touchwithEvent:(UIEvent*)event59. 60. 上面的代码添加了UIView的事件处理。由于屏幕和Cocos2D采用不同的坐标系,所以我们需要进行坐标转换。 1)首先获取屏幕坐标 2)将屏幕坐标转换为OpenGL的坐标 3)将OpenGL的坐标转换为Cocos2D的坐标。 从运行结果可以看出Node1和Node2打印出的坐标相同。因为Cocos2D给我们写了covertTouchToNodeSpace方法,可以看看它的源码:cpp view plaincopyprint?1. -(CGPoint)convertTouchToNodeSpace:(UITouch*)touch2. 3. CGPointpoint=touchlocationInView:touchview;4. point=CCDirectorsharedDirectorconvertToGL:point;5. returnselfconvertToNodeSpace:point;6. 至于为什么OpenGL和Node1输出既然相同,为什么还要使用convertToNodeSpace,由于能力有限,希望大牛们能给告诉我答案。 UIView输出的是将Cocos2D坐标转换为屏幕即quartz坐标。 4) convertTouchToNodeSpaceAR是将触摸点转换为相对于rectSprite的坐标8、判断触摸点是否在制定的精灵上 cpp view plaincopyprint?1. -(BOOL)ccTouchBegan:(UITouch*)touchwithEvent:(UIEvent*)event2. CGPointpoint=touchlocationInView:touchview;3. CCLOG(ScreencoordX:%.2fcoordY:%.2f,point.x,point.y);4. 5. point=CCDirectorsharedDirectorconvertToGL:point;6. CCLOG(OpenGLcoordX:%.2fcoordY:%.2f,point.x,point.y);7. 8. point=selfconvertToNodeSpace:point;9. CCLOG(CCNode1coordX:%.2fcoordY:%.2f,point.x,point.y);10. 11. point=selfconvertTouchToNodeSpace:touch;12. CCLOG(CCNode2coordX:%.2fcoordY:%.2f,point.x,point.y);13. 14. /point=CCDirectorsharedDirectorconvertToUI:point; 15. /CCLOG(UIViewcoordX:%.2fcoordY:%.2f,point.x,point.y); 16. CCLOG(%d,rectSprite.textureRect.size.width);17. 18. CGRectrect=rectSpritetextureRect;19. rect=CGRectMake(0,0,rect.size.width,rect.size.height);20. CCLOG(orgX:%.2forgY:%.2fwidth:%.2fheight:%.2f,rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);21. 22. point=rectSpriteconvertTouchToNodeSpaceAR:touch;23. CCLOG(TouchARcoordX:%.2fcoordY:%.2f,point.x,point.y);24. if(CGRectContainsPoint(rect,point)25. CCLOG(YoutouchedintherectSprite);26. 27. returnYES;28. 9、获取触摸的是哪个tile,并改变该tile. cpp view plaincopyprint?1. CCSprite*rectSprite;2. CCTMXTiledMap*gameWorld;3. intspeed=10;4. -(id)init5. 6. /alwayscallsuperinit 7. /Applerecommendstore-assignselfwiththesuperreturnvalue 8. if(self=superinit)9. gameWorld=CCTMXTiledMaptiledMapWithTMXFile:PositionText.tmx;10. selfaddChild:gameWorld;11. CGSizewinSize=CCDirectorsharedDirectorwinSize;12. CCLOG(gameWorld.mapSize.width:%.2fgameWorld.mapSize.height:%.2f,gameWorld.mapSize.width,gameWorld.mapSize.height);13. CCLOG(gameWorld.tileSize.width:%.2fgameWorld.tileSize.height:%.2f,gameWorld.tileSize.width,gameWorld.tileSize.height);14. CCLOG(winSize.width:%.2fwinSize.height:%.2f,winSize.width,winSize.height);15. 16. CCSprite*pointSprite=CCSpritespriteWithFile:point.png;17. gameWorldaddChild:pointSpritez:2tag:1;18. pointSprite.position=ccp(20,20);19. pointSprite.anchorPoint=ccp(0.5,0.5);20. 21. 22. rectSprite=CCSpritespriteWithFile:myrect.png;23. gameWorldaddChild:rectSpritez:0tag:3;24. rectSprite.position=ccp(40,40);25. rectSprite.anchorPoint=ccp(0,0);26. 27. selfsetIsTouchEnabled:YES;28. 29. returnself;30. 31. 32. -(void)registerWithTouchDispatcher33. CCTouchDispatchersh

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论