I am working on a game where one spaceship("Origin") can shoot a dumb projectile("Projectile") at another spaceship("Target").

Since the target is moving we will have to lead the target. The projectile will move at a given speed (to be clear I differentiate between "velocity" which i use when talking about a vector and "speed" when i am talking about the length of said vector).

I am trying to calculate the point where I will have to aim in order to hit the target (assuming it does not change its velocity).

I tried this example.


This is part of the "projectile" class that a wrote. self.targetVessel is the target self.originVessel is the shooter this function is called one in the constructor so that self.originVessel.velocity is the starting velocity self.totalSpeed is the "kick" that the projectile gets from the shooter

    def takeAim (self):
    t = 0

    #self.totalSpeed += math.sqrt(np.dot(self.originVessel.velocity, self.originVessel.velocity))

    posRel = self.pos - self.targetVessel.pos 
    velRel = self.originVessel.velocity - self.targetVessel.velocity
    #velRel =  - self.targetVessel.velocity #this hits the target but the speeds don't add up

    a = (np.dot(velRel, velRel))-(self.totalSpeed**2)
    b = 2.0 * (np.dot(velRel,posRel))
    c = np.dot(posRel, posRel)

    disc = (b*b) - (4.0*a*c)

    print("Disc: ", disc)

    if disc < 0:
        print("Target is too fast - no point shooting!")
        t0 = (-b - math.sqrt(disc)) / (2.0*a)
        t1 = (-b + math.sqrt(disc)) / (2.0*a)

        print("t0: ", t0)
        print("t1: ", t1)

        if t0 < 0:
            t = t1
            print ("Choosing t1")
        elif t1 < 0:
            t = t0
            print ("Choosing t0")
            if t0 < t1:
                t = t0
                print("Choosing t0")
                t = t1
                print("Choosing t1")

    shoot = velRel + (posRel / t)
    self.velocity =  shoot + self.targetVessel.velocity
    self.aimPoint = self.targetVessel.pos + self.targetVessel.velocity*t
    targetDirection = self.aimPoint-self.pos
    targetDirection = targetDirection / math.sqrt(np.dot(targetDirection,targetDirection))
    self.velocity = (targetDirection * self.totalSpeed)

1 Answer 1


I toyed with that problem. My program had photon torpedoes that went a certain distance (game loops) and then exploded. And if the target (or any target) was within the blast radius, it took damage. I did this:

First, I calculated the distance (hypotenuse) from the shooter to the target.

Then I divided that by the velocity of the projectile. That gives an estimate of the games loops the target will travel while the projectile is in flight.

Then I multiplied the deltax and deltay of the target by this 'game loops' variable and added that to the location of the target to get an estimated location of where it might be when the projectile gets there.

Then I recalculate the range (hypotenuse) to the new location to get the actual number of game loops it will take for the projectile to travel from the shooter to the target and then use arctangent to get the angle and then sine and cosine to calculate the deltax and deltay for the projectile.

With that I have the info for the projectile to travel to where the target is likely to be (if it hasn't changed direction).

This is kind of what my code looks like to calculate angle and then photonXch and photonYch and loops to target once you have the predicted new location of the target. Opposite and adjacent are the two sides of a right triangle...you know...a^2+b^2=c^2



#comment...if either the opposite or the adjacent are 0, I make them equal to 1 to avoid dividing by zero or dividing into zero





xsign and ysign are based on whether the target location is left/right up/down from the shooter and my simple way of determining if the resulting Xch and Yc are negative or positive. In other words, if the targetx>shooterx, then the Xch will be positive, else negative and if the targety>shootery, then the Ych is positive else negative.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .