原文链接地址:http://www.iphonegametutorials.com/2010/09/10/cocos2d-sprite-tutorial-part-2/

  上一篇教程中,我们留下了我们孤独的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:

  1. 计算touch点到dragon当前位置的向量
  2. 计算这个向量的长度(这里是像素长度)
  3. 计算move向量的弧度
  4. 把弧度转换成角度(因为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部分教程见!

    下篇教程见!

作者: 子龙山人 发表于 2011-07-20 15:05 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"