到目前为止都很美好!

但是却有一点奇怪,因为炮塔一下子跳转到指定位置去射击,并不是平滑的跟随触摸去转动到指定位置.你可以修复这个问题,但是这需要略微一点的重构(refactoring).

首先打开HelloWorldLayer.h,在你的类中添加下面一个实例变量:

CCSprite *_nextProjectile;

然后回到HelloWorldLayer.m中按如下代码修改ccTouchesEnded方法:

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    if (_nextProjectile != nil) return;

    // Choose one of the touches to work with
    UITouch *touch = [touches anyObject];
    CGPoint location = [self convertTouchToNodeSpace:touch];

    // Set up initial location of projectile
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    _nextProjectile = [[CCSprite spriteWithFile:@"projectile2.png"] retain];
    _nextProjectile.position = ccp(20, winSize.height/2);

    // Determine offset of location to projectile
    CGPoint offset = ccpSub(location, _nextProjectile.position);

    // Bail out if you are shooting down or backwards
    if (offset.x <= 0) return;

    // Determine where you wish to shoot the projectile to
    int realX = winSize.width + (_nextProjectile.contentSize.width/2);
    float ratio = (float) offset.y / (float) offset.x;
    int realY = (realX * ratio) + _nextProjectile.position.y;
    CGPoint realDest = ccp(realX, realY);

    // Determine the length of how far you're shooting
    int offRealX = realX - _nextProjectile.position.x;
    int offRealY = realY - _nextProjectile.position.y;
    float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
    float velocity = 480/1; // 480pixels/1sec
    float realMoveDuration = length/velocity;

    // Determine angle to face
    float angleRadians = atanf((float)offRealY / (float)offRealX);
    float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
    float cocosAngle = -1 * angleDegrees;
    float rotateDegreesPerSecond = 180 / 0.5; // Would take 0.5 seconds to rotate 180 degrees, or half a circle
    float degreesDiff = _player.rotation - cocosAngle;
    float rotateDuration = fabs(degreesDiff / rotateDegreesPerSecond);
    [_player runAction:
     [CCSequence actions:
      [CCRotateTo actionWithDuration:rotateDuration angle:cocosAngle],
      [CCCallBlock actionWithBlock:^{
         // OK to add now - rotation is finished!
         [self addChild:_nextProjectile];
         [_projectiles addObject:_nextProjectile];

         // Release
         [_nextProjectile release];
         _nextProjectile = nil;
     }],
      nil]];

    // Move projectile to actual endpoint
    [_nextProjectile runAction:
     [CCSequence actions:
      [CCMoveTo actionWithDuration:realMoveDuration position:realDest],
      [CCCallBlockN actionWithBlock:^(CCNode *node) {
         [_projectiles removeObject:node];
         [node removeFromParentAndCleanup:YES];
    }],
      nil]];

    _nextProjectile.tag = 2;

    [[SimpleAudioEngine sharedEngine] playEffect:@"pew-pew-lei.caf"];
}

看起来代码不少,但是实际你并没有修改太多,大多数都仅仅是很小的重构,以下是代码做出的改变:

  • 在方法开始处如果_nextProjectile不为nil则直接退出,意思是你正在处理射击操作
  • 之前你使用的是一个名为projectile的局部变量,然后立即把它添加到场景中.在新的版本中你创建了一个实例变量_nextProjectile,但是没有立即添加到场景中.
  • 你定义了炮塔旋转的速度为180 / 0.5,意味着半秒钟旋转180度.
  • 去计算旋转特定的角度需要多长时间
  • 然后开始一个顺序action去旋转炮塔到正确的角度,然后调用一个block去将导弹添加到场景中.

偶鸟,试一试吧!编译运行项目,然后现在炮塔应该旋转的平滑多了 ;)

原文地址:Rotating Turrets: How To Make A Simple iPhone Game with Cocos2D 2.X Part 2

Cocos2D旋转炮塔到指定角度(三)的更多相关文章

  1. Cocos2D旋转炮塔到指定角度(一)

    原文地址:Rotating Turrets: How To Make A Simple iPhone Game with Cocos2D 2.X Part 2 翻译有节选和删除. 在你旋转炮塔之前,首 ...

  2. Cocos2D旋转炮塔到指定角度(二)

    增加如下代码到ccTouchesEnded方法中,就在你在导弹精灵上调用runAction之前: // Determine angle to face float angleRadians = ata ...

  3. 【Cocos2d入门教程七】三分钟看懂Cocos2d坐标系

    无论是搞2d还是3d开发,最需要搞清楚的就是坐标系,这部分混乱的话就没啥搞头了.所以玩cocos2d,一上来就需要先把各种与坐标有关的东西搞清楚. 1.OpenGL坐标系 Cocos2d-x使用的是O ...

  4. 使用cmd查看电脑连接过的wifi密码并将密码发送至指定邮箱(三)

    之前,我写了使用cmd查看电脑连接过的wifi密码(二)和使用cmd查看电脑连接过的wifi密码(一)但其中的功能不完善,在本次的更新中新增了更多的功能,其实2018/10/24 就更新完成了,一直拖 ...

  5. osg指定向量旋转指定角度

    向量AB,沿着n旋转10度 osg::Vec3 left = AB*osg::Matrix::rotate(osg::inDegrees(10), n); osg::Vec3 right = AB*o ...

  6. python入门学习笔记(三)

    10.函数 求绝对值的函数 abs(x) 也可以在交互式命令行通过 help(abs) 查看abs函数的帮助信息.调用 abs 函数:>>> abs(100)100>>& ...

  7. 用MATLAB绘制折线图,x轴为字符串,并旋转一定的角度!!!

    先上代码,然后再一行一行解释: x=1:37; %这一行其实一开始,写的时候是没有的,后来需要给X轴上规定几个刻度才加上的 plot(x,Y,'linewidth',2); %以x为自变量,y为因变量 ...

  8. mysql中影响myisam引擎写入性能的三项设置

    一.LOW_PRIORITY1.对于myisam默认是写操作优先,读操作滞后.通过该项更改,可以使读操作优先,写操作在有空闲的时候再写入.但该项可能在理论上造成,写被永远阻塞. SQL语句中使用示例: ...

  9. C#GDI+基础(三)画刷详解

    SolidBrush:一般的画刷,通常只用一种颜色去填充GDI+图形 创建一般画刷: SolidBrush sbBrush1 = new SolidBrush(Color.Green); HatchB ...

随机推荐

  1. 数据挖掘_requests模块的get方法

    关于requests模块 之前在跟大家讲通过字典列表批量获取数据的时候用过这个模块 安装过程就不再讲解了 requests模块是python的http库,可以完成绝大部分与http应用相关的工作,所以 ...

  2. Golang学习笔记:channel

    channel channel是goroutine之间的通信机制,它可以让一个goroutine通过它给另一个goroutine发送数据,每个channel在创建的时候必须指定一个类型,指定的类型是任 ...

  3. 58. Length of Last Word(easy, 字符串问题)

    Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...

  4. include和require的区别比较

    require 的使用方法如 require("MyRequireFile.php"); .这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require ...

  5. Java不走弯路教程(前言)

    本教程的程序基于Windows开发,所以你需要有一台安装Windows操作系统的电脑. 前言本教程将带你完成Java的初学和WEB框架的开发,学完本教程,你将完成对Java的入门并且对下一步不再迷茫. ...

  6. ftp传二进制文件时一定要用二进制模式,否则内容会有变化,造成后处理莫名其妙的错误,还以为传输前后内容一致,其实已变化。

    ftp传二进制文件时一定要用二进制模式,否则内容会有变化,造成后处理莫名其妙的错误,还以为传输前后内容一致,其实已变化.

  7. 码农代理免费代理ip端口字段js加密破解

    起因 之前挖过爬取免费代理ip的坑,一个比较帅的同事热心发我有免费代理ip的网站,遂研究了下:https://proxy.coderbusy.com/. 解密 因为之前爬过类似的网站有了些经验,大概知 ...

  8. Dynamics CRM2016 Web API之获取查找字段的text及选项集的text

    本篇再来介绍个web api的功能,关于lookup的text这里只是略带,因为有expand,现有的web api就能实现,主要提的是选项集的text,我们通过基本的查询api查出来的字段值只带有v ...

  9. Programming In Scala笔记-第七章、Scala中的控制结构

    所谓的内建控制结构是指编程语言中可以使用的一些代码控制语法,如Scala中的if, while, for, try, match, 以及函数调用等.需要注意的是,Scala几乎所有的内建控制结构都会返 ...

  10. [boost][filesystem] 扫描给定目录下所有项

    Intro. Boost的filesystem可以用来扫描给定目录下的所有项. 实现 具体实现代码如下: 需要包含的头文件和使用的命名空间: #include <boost/filesystem ...