1

I have a heat seeking missile in a space shooter game that follows a moving target. The missile follows the moving target well enough, but I want it to be constantly rotated in the direction of the target. My current code is as follows:

   -(void)updateHeatSeekerAngleTo:(CGPoint)direction
   {
       CGFloat angle = atan2f(direction.y, direction.x);
       _heatSeeker.zRotation = angle;       
   }

This method is then called in didSimulatePhysics (because this renders sooner than update:) using the following:

[self updateHeatSeekerAngleTo:_target.position];

As mentioned, the missile follows the moving target beautifully, however, it has a VERY delayed rotation effect, and often follows the moving target in a sideways position, then finally pointing towards the target as it draws nearer. I tested the code on a stationary missile sprite and the stationary missile constantly points to the target as the target moves, but it does not do this when the missile is in motion. How can I get the missile to point to the moving target constantly while in motion?

wtivie05
  • 45
  • 2

1 Answers1

1

Sounds like your target is deploying countermeasures when you fire your missile at it...

Jokes aside, I suspect it is probably the 90 degree offset you are not taking into account. A node's zRotation "zero" angle is actually on the right of the node or what we would consider 90 degrees. This can cause a lot of confusion when dealing with angles and zero being straight up.

Look at the sample project code below. You can tap/click and drag the square around the screen and the missile tip will track the target. You can use the code to correct your issue.

#import "GameScene.h"
@implementation GameScene {
     SKSpriteNode *node0;
     SKSpriteNode *node1;
}

-(void)didMoveToView:(SKView *)view {
    self.backgroundColor = [SKColor whiteColor];

    node0 = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(50, 50)];
    node0.position = CGPointMake(500, 500);
    [self addChild:node0];

    node1 = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:CGSizeMake(10, 50)];
    node1.position = CGPointMake(300, 350);
    [self addChild:node1];

    SKSpriteNode *node0Tip = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(10, 10)];
    node0Tip.position = CGPointMake(0, 25);
    [node1 addChild:node0Tip];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    for (UITouch *touch in touches) {
        CGPoint touchLocation = [touch locationInNode:self];

        node0.position = touchLocation;

        // calculate angle between object and touch
        float deltaY = touchLocation.y - node1.position.y;
        float deltaX = touchLocation.x - node1.position.x;
        float moveBydegrees = atan2(deltaY, deltaX) * 180 / 3.14159265359;

        // convert degrees to radians
        float moveByRadians = moveBydegrees * M_PI / 180;

        node1.zRotation = (moveByRadians-1.5707963268); // account for 90 degree offset
    }
}


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

     for (UITouch *touch in touches) {
         CGPoint touchLocation = [touch locationInNode:self];

        node0.position = touchLocation;

        // calculate angle between object and touch
        float deltaY = touchLocation.y - node1.position.y;
        float deltaX = touchLocation.x - node1.position.x;
        float moveBydegrees = atan2(deltaY, deltaX) * 180 / 3.14159265359;

        // convert degrees to radians
        float moveByRadians = moveBydegrees * M_PI / 180;

        node1.zRotation = (moveByRadians-1.5707963268); // account for 90 degree offset
    }
}
sangony
  • 11,636
  • 4
  • 39
  • 55