用cocos2d-x做一个简单的windows phone 7游戏:旋转炮塔(二)

本教程介绍如何使用Cocos2d-x for XNA引擎实现游戏中的旋转炮塔功能,包括炮塔根据触屏位置旋转并对准目标射击的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本教程基于子龙山人翻译的cocos2dIPHONE教程,用cocos2d-x for XNA引擎重写,加上我一些加工制作。教程中大多数文字图片都是原作者和翻译作者子龙山人,还有不少是我自己的理解和加工。感谢原作者的教程和子龙山人的翻译。本教程仅供学习交流之用,切勿进行商业传播。

子龙山人翻译的Iphone教程地址:http://www.cnblogs.com/andyque/articles/1997820.html

Iphone教程原文地址:http://www.raywenderlich.com/692/rotating-turrets


旋转炮塔来改变射击的方向。许多游戏都有这个功能,

在这个教程中,将会详细地讲解如何实现这个功能,即如何把旋转炮塔的功能添加到一个游戏当中去。

准备工作

  如果你看完并实践了上一个教程,你可以继续使用那个工程。如果没有的话,那么下载这个链接的代码吧。

  接下来,下载新的 player sprite projectile sprite图片,然后把它们加到Content工程的images目录里面。并修改原来的精灵初始化代码。

// In the init method
CCSprite player = CCSprite.spriteWithFile(@"images/player2");
// In the ccTouchesEnded method
CCSprite projectile = CCSprite.spriteWithFile(@"images/Projectile2");
编译并运行你的工程,如果一切顺利的话,你将会看到一个炮塔正在发射子弹。然后,这并不是很好,因为炮塔在射击的时候并没有面朝那个方向。因此,接下来让我们来解决这个问题。

旋转并射击

  在我们旋转炮塔之前,首先,我们需要保存Player精灵的引用,以便后面旋转它的时候使用。把Player精灵的声明提到类当中去:

CCSprite player;

修改init中的代码为:

player = CCSprite.spriteWithFile(@"images/player2");
好了,现在让我们取出player对象的引用并且旋转它吧!为了旋转它,我们首先需要计算出旋转的角度。为了解决这个问题,想想我们在高中时候学过的三角代数吧。还记得sin cos tan吗?为了便于理解,下面使用一张图来解释一下:tan = 对面/邻边。

  如上所示,我们想要旋转的角度是arctangent(angle),即对offY/offX求arctangent运算。

  然而,这里还有两件事情,我们需要放在心上。首先,当我们计算actangent(offY/offX)的时候,这个结果是弧度,但是cocos2d使用的却是角度。还好,cocosd2d提供了一个非常方便的宏,可以使得角度和弧度之间方便转化。

  第二点,我们假定上面的图中angle的偏转是正20度,但是,cocos2d里面顺时针方向为正(而不是上图所示的逆时针为正)。让我们看到下面这个图:

  因此,为了得到正确的方向,我们把运算结果乘以一个-1就可以了。比如,如果我们把上面那幅图片里的角度乘以-1的话,我们就得够得到-20度,这个角度其实就是逆时针方向的20度。(感觉老外说话好啰嗦啊,聪明的读者恐怕早就明白了吧!:)

  好了,讲得够多了!让我们来写一点代码吧。在ccTouchesEnded里面加入以下代码,添加位置在你的projectile runAction之前。

            //Determine angle to face
            float angleRadians = (float)Math.Atan(offRealY / offRealX);
            float angleDegrees = MathHelper.ToDegrees(angleRadians);
            float cocosAngle = -1 * angleDegrees;
			player.rotation = cocosAngle;

  编译并运行工程,现在我们的炮塔在射击的时候可以改变方向了。

旋转之后再射击

  目前来说还不错,但是有一点点怪。因为,这个炮塔好像突然一下跳到一个方向射击,有点不够流畅。我们可以解决这个问题,但是在这之前,我们需要重构一下代码。

  首先,打开GamePlayLayer类,然后在你的类里添加如下成员变量:

CCSprite nextProjectile = null;

然后,修改你的ccTouchesEnded方法,并且添加一个新的方法,叫做finishShoot,如下所示:

 

        public override void ccTouchesEnded(List<CCTouch> touches, CCEvent event_)
        {
            if (nextProjectile != null)
                return;

            CCTouch touch = touches.FirstOrDefault();
            CCPoint location = touch.locationInView(touch.view());
            location = CCDirector.sharedDirector().convertToGL(location);

            //set up initial location of projectile
            CCSize winSize = CCDirector.sharedDirector().getWinSize();
            //CCSprite projectile = CCSprite.spriteWithFile(@"images/Projectile");
            nextProjectile = CCSprite.spriteWithFile(@"images/Projectile2");
            nextProjectile.position = new CCPoint(20, winSize.height / 2);

            //Determine offset of location to projectile

            float offX = location.x - nextProjectile.position.x;
            float offY = location.y - nextProjectile.position.y;

            //Bail out if we are shooting or backwards
            if (offX <= 0)
            {
                return;
            }



            //Determine where we wish to shoot the projectile to
            float realX = winSize.width + nextProjectile.contentSize.width / 2;
            float ratio = offY / offX;
            float realY = realX * ratio + nextProjectile.position.y;
            CCPoint realDest = new CCPoint(realX, realY);

            //Determine the length of how far we're shooting
            float offRealX = realX - nextProjectile.position.x;
            float offRealY = realY - nextProjectile.position.y;
            float length = (float)Math.Sqrt(offRealX * offRealX + offRealY * offRealY);
            float velocity = 480 / 1;//480pixls/lsec
            float realMoveDuration = length / velocity;


            //Determine angle to face
            float angleRadians = (float)Math.Atan(offRealY / offRealX);
            float angleDegrees = MathHelper.ToDegrees(angleRadians);
            float cocosAngle = -1 * angleDegrees;

            float rotateSpeed = (float)(0.5 / Math.PI);//Would take 0.5 seconds to rotate 0.5 radians ,or half a circle
            float rotateDuration = Math.Abs(angleRadians * rotateSpeed);
            player.runAction(CCSequence.actions(CCRotateTo.actionWithDuration(rotateDuration,cocosAngle), CCCallFunc.actionWithTarget(this, finishShoot)));
            //Move projectile to actual endpoint
            nextProjectile.runAction(CCSequence.actions(CCMoveTo.actionWithDuration(realMoveDuration, realDest),
                CCCallFuncN.actionWithTarget(this,spriteMoveFinished)));
            nextProjectile.tag = 2;
            
            //SimpleAudioEngine.sharedEngine().playEffect(@"resource/pew-pew-lei");
        }

        void finishShoot()
        { 
            // Ok to add now , we are finished rotation
            this.addChild(nextProjectile);
            _projectiles.Add(nextProjectile);
            nextProjectile = null;
        }


        看上去好像有许多代码,但是,实际上我们改动的并不多--大部分只是做一些小小的重构。下面是我们所修改的内容的一个列表: 

  1.  在函数开头检查nextProjectile的值是否为nil。这意味着我们当前的touch事件正发生在射击过程之中。也就是说,炮塔已经发射出一个子弹了。 .
  2. 之前,我们使用一个projectile的局部变量,并把它加入到了当前的场景中。在这个版本中,我们增加了一个nextProjectile的成员变量,但是并没有马上加到当前场景中。因为后要还要使用。
  3.  .定义炮塔旋转的角度,半秒钟旋转半个圆。记住,一个圆有2 PI个弧度。 .
  4. 计算旋转特定的角度需要多长时间,这里是拿弧度乘以速度。 .
  5. 接下来,我们使用一个sequence action来旋转我们的炮塔。最后,调用一个函数,把projectile加入到当前场景当中去。  

好,大功告成!编译并运行工程,现在炮塔可以旋转,并且很流畅地射击了!本次工程下载:http://dl.dbank.com/c0cvo9f1gc    

 继续学习:用cocos2d-x做一个简单的windows phone 7游戏:更猛的怪兽和更多的关卡(三)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值