Make a simple Windows Phone 7 game with cocos2d-x: rotating turret (2)

Source: Internet
Author: User
Tags sin cos

This tutorial is based on the Child Dragon Mountain Man translation cocos2d iPhone tutorial, rewrite with cocos2d-x for xNa engine, plus some of my processing and production. In the tutorial, most of the text images are from the original author and the author of the translation, Long Shan, and many others are my own understandings and processing. I would like to thank the original author for his tutorial and the translation of Zilong shangren. This tutorial is only for learning and communication purposes. Do not conduct commercial communications.

IPhone tutorial address: http://www.cnblogs.com/andyque/articles/1997820.html

IPhone tutorial original address: http://www.raywenderlich.com/692/rotating-turrets


Rotate the turret to change the shooting direction. Many games have this function,

In this tutorial, we will explain in detail how to implement this function, that is, how to add the turret rotation function to a game.


Preparations


If you have read and practiced the previous tutorial, you can continue to use the project. If not, download the code of this link.

Next, download the new
Player Sprite and
Projectile sprite image, and then add them to the images directory of the content project. And modify the original genie initialization code.

// In the init method
CCSprite player = CCSprite.spriteWithFile (@ "images / player2");
// In the ccTouchesEnded method
CCSprite projectile = CCSprite.spriteWithFile (@ "images / Projectile2");
Compile and run your project. If all goes well, you will see a turret firing bullets. Then, this is not very good, because the turret did not face in that direction when shooting. So, let's solve this problem next.

Spin and shoot
Before we rotate the turret, first of all, we need to save the reference of the Player sprite to use later when we rotate it. Put the player sprite's statement into the class:

CCSprite player;
Modify the code in init to:

player = CCSprite.spriteWithFile (@ "images / player2");
Okay, now let's take the player object reference and rotate it! In order to rotate it, we first need to calculate the angle of rotation. To solve this problem, think about the triangle algebra we learned in high school. Remember sin cos tan? For ease of understanding, the following uses a picture to explain: tan = opposite / adjacent side.

As shown above, the angle we want to rotate is arctangent (angle), that is, the arctangent operation for offY / offX.

However, there are two things here that we need to keep in mind. First, when we calculate actangent (offY / offX), the result is in radians, but cocos2d uses angles. Fortunately, cocosd2d provides a very convenient macro that can easily convert between angles and radians.

The second point, we assume that the deflection of the angle in the above figure is positive 20 degrees, but the clockwise direction in cocos2d is positive (instead of the counterclockwise shown as positive). Let us see the following picture:


Therefore, in order to get the correct direction, we can multiply the operation result by a -1. For example, if we multiply the angle in the picture above by -1, we have to get -20 degrees, which is actually 20 degrees counterclockwise. (It feels so long-winded for foreigners to speak, I am afraid that smart readers will understand it already! :)

Okay, enough talk! Let's write a little code. Add the following code in ccTouchesEnded, add the position before your 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;
Compile and run the project, now our turret can change direction when shooting.

Shoot after spinning
It's not bad at present, but it's a little strange. Because, this turret suddenly jumped into one direction to shoot, and it was not smooth enough. We can solve this problem, but before that, we need to refactor the code.

First, open the GamePlayLayer class, and then add the following member variables to your class:

CCSprite nextProjectile = null;
Then, modify your ccTouchesEnded method and add a new method called finishShoot, as shown below:

 

        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;
        }
        It seems that there is a lot of code, but in fact, we have not changed much-most of them are just doing some small refactoring. The following is a list of what we have modified:

Check whether the value of nextProjectile is nil at the beginning of the function. This means that our current touch event is happening during the shooting process. In other words, the turret has fired a bullet. .
Previously, we used a local variable of projectile and added it to the current scene. In this version, we added a member variable of nextProjectile, but it was not immediately added to the current scene. Because it will be used later.
. Define the rotation angle of the turret, and rotate half a circle in half a second. Remember, a circle has 2 PI radians. .
Calculate how long it takes to rotate a specific angle. Here we multiply the radian by the speed. .
Next, we use a sequence action to rotate our turret. Finally, call a function to add projectile to the current scene.
Okay, you're done! Compile and run the project. Now the turret can rotate and shoot very smoothly! Download this project: http://dl.dbank.com/c0cvo9f1gc

 Continue learning: use cocos2d-x to make a simple windows phone 7 game: more fierce monsters and more levels (3)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.