3

I created a "ship" node to move along the circular path as follows:

self.orbit = [OrbitManager getCirclePathWithCenter:centerRealPt radius:radius startingAngle:angelFromCenter isClockwise:self.isClockwise];

SKAction* orbitAction = [SKAction followPath:self.orbit asOffset:NO orientToPath:YES speed:300];

[self.ship.node runAction:orbitAction];

and I have a cannon which shoots a bullet by applying a velocity to it as follows:

bullet.node.physicsBody.velocity = [ActionHelper getVelocityFrom:bullet.node toNodeB:self.target speed:bullet.speed];

as the ship is moving along the path. But the bullet will miss every time. How can I calculate the position which the cannon should aim at, with a given speed?

jscs
  • 63,694
  • 13
  • 151
  • 195
Siu Chung Chan
  • 1,686
  • 1
  • 14
  • 31
  • Sounds to me like you are looking to calculate trajectory, you need to figure out at what point in time the 2 objects will collide, that requires some math – Knight0fDragon Nov 01 '16 at 18:59

2 Answers2

1

This is my Objective-C (it is actually a C function) Solution to fire a projectile in to a moving target.

You can look at the derivations In this SO topic

This will give you a hit point and an angle to shoot, you can simply translate it to velocity because you know the angle and a projectile speed, it will be something like:

`CGVector Velocity = CGVectorMake(speed * cos(theta), speed * sin(theta));`


BOOL calculateAngleToShoot(CGVector targetVelocity, CGPoint targetPosition, CGPoint selfPos,CGFloat projectileSpeed,CGFloat *theta, CGPoint * hitPoint)
{
    CGFloat dx = targetPosition.x - selfPos.x;
    CGFloat dy = targetPosition.y - selfPos.y;

    CGVector v = targetVelocity;

    CGFloat a = v.dx * v.dx + v.dy * v.dy - projectileSpeed * projectileSpeed;
    CGFloat b = 2 * (v.dx * dx + v.dy * dy);
    CGFloat c = v.dx * v.dx + v.dy * v.dy;

    CGFloat q = b * b - 4 *  a * c;
    if (q < 0)
    {
        //Dead End;
        return NO;
    }
    CGFloat t = ((a < 0 ? -1 : 1) * sqrt(q) - b) / (2 * a);

    // Aim for where the target will be after time t
    dx += t * v.dx;
    dy += t * v.dy;
    *theta = atan2(dy, dx);

    *hitPoint = CGPointMake(targetPosition.x + v.dx * t, targetPosition.y + v.dy * t);
    return YES;
}
Community
  • 1
  • 1
Coldsteel48
  • 3,482
  • 4
  • 26
  • 43
1

After some investigation I got how to get the answer

first I need to get the distance(d) between the target and the center and the time for the bullet from center to the target. since the ship is moving along the circle, so the radius is also equals to distance(d)

CGFloat timeToArriveTarget = bullet.speed/distance;
CGFloat angularSpeed = bullet.speed/distance;

Find the angle moved within this period of time

CGFloat angle = angularSpeed * timeToArriveTarget;

CGFloat x = self.target.position.x;
CGFloat y = self.target.position.y;
CGFloat a = bullet.node.position.x;
CGFloat b = bullet.node.position.y;

and finally using this formula: details are give by this link https://math.stackexchange.com/a/266837

CGPoint targetPt = CGPointMake((x - a) * cos(angle) - (y - b) * sin(angle) + a, (x - a) * sin(angle) + (y - b) * cos(angle) + b);

bullet.node.physicsBody.velocity = [ActionHelper getVelocityFrom:bullet.node.position toPtB:targetPt speed:bullet.speed];

the getVelocity function is given by

+(CGVector)getVelocityFrom:(CGPoint)ptA toPtB:(CGPoint)ptB speed:(CGFloat)speed{

CGPoint targetPosition = ptB;
CGPoint currentPosition = ptA;

double angle = [MathHelper getRotateAngleFrom:currentPosition toTargetPosition:targetPosition];
double velocityX = speed * cos(angle);
double velocityY = speed * sin(angle);

CGVector newVelocty = CGVectorMake(velocityX, velocityY);
return newVelocty;

}

Community
  • 1
  • 1
Siu Chung Chan
  • 1,686
  • 1
  • 14
  • 31