cocos2d精灵教程:第二部分
上一篇教程中,我们留下了我们孤独的dragon在屏幕中间。。。然而,90%的动画并没有应用到,那可是我们花了很大力气才建立好的呀!太遗憾了!所以,我们这篇教程要弥补这个缺憾。我们将添加touch控制,以此来捕获用户的输入,并根据用户手指的方向来选择一个合适的动画给dragon播放。你就可以用手在屏幕上滑动来指挥dragon移动了。
这里有本教程的完整源代码。
对于cocos2d来说,如果你想要使用touch控制的话,直接告诉它就可以了,如下所示:
self.isTouchEnabled = YES; 上面的self应该是CCLayer或者CCLayer的派生类,因为isTouchEnabled 只在CCLayer中定义了。如果isTouchEnabled为YES,那么在onEnter方法进入的时候就会调用registerWithTouchDispatcher方法。这里我们需要覆盖它,因为我们要使用Targeted touch事件,如果不覆盖,默认就是使用standarded touch事件。
-(void) registerWithTouchDispatcher{ [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];}
TargetedTouchDelegate.
使用这种类型的delegate有两种好处:
1.你不需要再处理NSSets了,CCTouchDispatcher 为了做了分离工作。每次调用的时候,你都会得到一个唯一的UITouch。
2.你可以激活touch事件,只需要在ccTouchBegan方法里return Yes就可以了。当touchMove/ended/cancelled回调被触发的时候,dispatcher类会保证每次都更新UITouch。这样可以让你在处理multi-touch的时候,完全不用考虑,全部事情CCTouchDispatcher 已经为你做好了。
这里我们将要覆盖 “ccTouchBegan” 和“ccTouchEnded” --第一个方法当第一个touch事件开始的时候被调用,另外一个是touch结束的时候被调用。还有一个 “ccTouchMoved”方法,它是你的手一直按在屏幕上面的时候被调用的,这个方法我们在后面会涉及到。
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { return YES;}-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { } 因此,现在我们有工具和函数了,为什么不编写一些代码呢?
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { NSLog(@"ccTouchEnded"); CGPoint touchLocation = [touch locationInView: [touch view]]; touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation]; touchLocation = [self convertToNodeSpace:touchLocation]; CGPoint moveVector = ccpSub(touchLocation, _dragon.position); float distanceToMove = ccpLength(moveVector); CGFloat moveAngle = ccpToAngle(moveVector); CGFloat cocosAngle = CC_RADIANS_TO_DEGREES(-1 * moveAngle); float dragonVelocity = 480.0/3.0; float moveDuration = distanceToMove / dragonVelocity; cocosAngle += 23; if (cocosAngle < 0) cocosAngle += 360; int runAnim = (int)((cocosAngle)/45); [_dragon stopAction:_flyAction]; self.flyAction = [_flyActionArray objectAtIndex:runAnim]; [_dragon runAction:_flyAction]; self.moveAction = [CCSequence actions: [CCMoveTo actionWithDuration:moveDuration position:touchLocation], nil ]; [_dragon runAction:_moveAction];} 前面这三行是标准用法(现在的版本可以用一句话替换,叫self converTouchToNodeSpace,感兴趣的朋友可以查看相关源代码,和下面这句话是一样的)
CGPoint touchLocation = [touch locationInView: [touch view]];touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];touchLocation = [self convertToNodeSpace:touchLocation];
这里先得到屏幕坐标(就是你手指按下去的地方的坐标),然后把它转换成OpenGL坐标。而convertToNodeSpace函数就是把OpenGL的坐标转换成CCLayer的坐标。
理解屏幕坐标,OpenGL坐标和Node坐标很重要,希望朋友们多多实践。
CGPoint moveVector = ccpSub(touchLocation, _dragon.position);float distanceToMove = ccpLength(moveVector); CGFloat moveAngle = ccpToAngle(moveVector); CGFloat cocosAngle = CC_RADIANS_TO_DEGREES(-1 * moveAngle);float dragonVelocity = 480.0/3.0;float moveDuration = distanceToMove / dragonVelocity;cocosAngle += 23;if (cocosAngle < 0) cocosAngle += 360;int runAnim = (int)((cocosAngle)/45);
因此,现在我们需要计算出如何旋转dragon:
计算touch点到dragon当前位置的向量
计算这个向量的长度(这里是像素长度)
计算move向量的弧度
把弧度转换成角度(因为cocos2d使用的是角度)
为了得到统一的移动方法,而不用管dragon目前处在屏幕的哪个位置,我们设置了一个变量,保存dragon移动的速度常量(通过距离/时间计算得到的)。然后,我们把move向量的长度除以这个速度,就可以得到CCMoveTo action所需要的duration了)
这里我还做了一些有趣的事--因为得到的度数范围是-180到180,所以我把它加上360,这样的话,就不会有负数。而当我把这个度数再除以45的时候,就可以得到一个整数,这个整数刚好可以满足我之前定义的8(360/45 = 8)个方向的动画数组。也就是通过这个整数取得一个动画,然后给dragon播放。我这里还加了一个23,因为,当我在dragon的东边点击的时候,我不想让它在0~8这8个动画挑选的时候很迷茫。通过加上这个小的偏移,我可以计算得到精确的动画索引。(比如,第0个动画,当-23到23度的时候,我们都得到的是0)。如果你还是觉得很迷惑的话,不妨把“cocosAngle += 23″这句代码注释掉,然后看一看这句代码到底干了一件什么事。
[_dragon stopAction:_flyAction];self.flyAction = [_flyActionArray objectAtIndex:runAnim];[_dragon runAction:_flyAction];self.moveAction = [CCSequence actions:[CCMoveTo actionWithDuration:moveDuration position:touchLocation],nil];[_dragon runAction:_moveAction];
最后,我们停止先前的动画,然后基于前面计算的结果“int runAnim = (int)((cocosAngle)/45);”来选择一个新的动画让dragon来run。这样的话,当我们在屏幕上面点击的时候,就可以让dragon朝着正确的方向移动,并且播放正确的动画了。第2部分教程到这里就结束了,让我们第3部分教程见!
下篇教程见!
补充:综合编程 , 其他综合 ,