Cocos2D旋转炮塔到指定角度(三)

到目前为止都很美好!

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

时间: 2024-08-30 12:03:08

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

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

原文地址:Rotating Turrets: How To Make A Simple iPhone Game with Cocos2D 2.X Part 2 翻译有节选和删除. 在你旋转炮塔之前,首先你要计算出需要旋转的角度. 为了计算,回忆一下高中的三角学.还能记住助记词SOH CAH和TOA吗?它可以帮助你回忆三角形角的正切(Tangent)等于对边比临边,如下图所示: 就像上图显示的那样,你需要旋转的角度等于矩形的Y偏移除以X偏移. 不管怎样,这里有2件事需要记住: 首先,当你计算矩形(

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

增加如下代码到ccTouchesEnded方法中,就在你在导弹精灵上调用runAction之前: // Determine angle to face float angleRadians = atanf((float)offRealY / (float)offRealX); float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians); float cocosAngle = -1 * angleDegrees; _player.rotatio

电话诈骗百余万三嫌疑人被判刑

深圳特区报讯(记者 杨明铭 通讯员 罗淑芳)冒充司法人员实施电话诈骗,骗取百余万巨款.近日,由福田区人民检察院提起公诉的林某某.王某.江某某三人涉嫌诈骗一案成功获判,三名被告被一审分别判处3至7年有期徒刑,并处人民币3000至30000元罚金. 2010年5月5日,该诈骗团伙的其他人员(另案处理)冒充中山市公安局.检察院工作人员,致电被害人富某某,谎称富某某的银行卡被盗用,需要对其账户进行冻结,要求富某某将其银行账户资金全部转到安全账户内.被害人富某某对此信以为真,遂将其多个银行账户的存款共计人

【Foreign Key】Oracle外键约束三种删除行为

Oracle使用外键来限制子表中参考的字段值,要求子表中的数据必须在主表中存在.当主表的记录发生变化时导致外键参考唯一约束值发生了变化时,Oracle指定了三种动作:默认值(类似于restrict).delete cascade和delete set null.实际体验一下他们对删除操作的不同效果. 1.创建主表及子表并简单初始化几条数据1)创建主表t_parent,并初始化三条记录sec@ora10g> create table t_parent (parent_id int primary

IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)

首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context是图形上下文,可以将其理解为一块画布,我们可以在上面进行绘画操作,绘制完成后,将画布放到我们的view中显示即可,view看作是一个画框. 自己学习时实现的demo,希望对大家有帮助,具体的实现看代码,并有完美的注释解释,还有一些对我帮助的博文供大家参考.都在代码里面. 看一下demo效果图先: 自

【Linux驱动】linux内核模块简介

一. 摘要 这篇文章主要介绍了Linux内核模块的相关概念,以及简单的模块开发过程.主要从模块开发中的常用指令.内核模块程序的结构.模块使用计数以及模块的编译等角度对内核模块进行介绍.在Linux系统开发过程中,以模块的形式开发其重要性不言自明,而在嵌入式设备驱动开发中将驱动程序以模块的形式发布,更是极大地提高了设备使用的灵活性--用户只需要拿到相关驱动模块,再插入到用户的内核中,即可灵活地使用你的设备. 二. 文章提纲 1. 摘要 2. 文章提纲 3. 概述 4. 模块开发常用的指令 5. 内

掌握AJAX

ajax Ajax 由 HTML.JavaScript 技术.DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序.本文的作者是一位 Ajax 专家,他演示了这些技术如何协同工作 -- 从总体概述到细节的讨论 -- 使高效的 Web 开发成为现实.他还揭开了 Ajax 核心概念的神秘面纱,包括 XMLHttpRequest 对象. 五年前,如果不知道 XML,您就是一只无人重视的丑小鸭.十八个月前,Ruby 成了关注的中心,不知道 Ruby 的

PHP常用函数小全

  纪录了PHP的一些常用函数 usleep() 函数延迟代码执行若干微秒. unpack() 函数从二进制字符串对数据进行解包. uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID. time_sleep_until() 函数延迟代码执行直到指定的时间. time_nanosleep() 函数延迟代码执行若干秒和纳秒. sleep() 函数延迟代码执行若干秒. show_source() 函数对文件进行语法高亮显示. strip_whitespace() 函数返回已删除 PHP

用C#开发.NETCF蓝牙通信模块

 今天查其他资料,发现此处蓝牙开发,收了.以备后用.     在Windows Mobile软件开发中.Net正扮演着日益重要的角色,我们已经可以看到很多用.Net CF开发的软件,这些软件涉及到了日常应用的方方面面.在智能设备的软件开发中,无线互联是一个相当重要的一块,我们可以看到,红外几乎是所有智能设备的标配,而蓝牙也日益在越来越多的智能设备上出现,有了硬件,显然要有相应的软件相关的应用. 我们也知道,用.NET CF开发红外通信应用时相当轻松的,因为.NET CF中有一个命名空间Syste