Skip to navigation

Adding bullets to the world

Spawning bullets that leave tracer trails in the sky

One of the features of Aviator that the manual includes in its list of features is the fact that "the aircraft bullets, once fired, will continue to move through space in the direction fired, independent of subsequent aircraft manoeuvres". Of course, this feature is pretty essential when the "game" aspect of your sophisticated flight simulator involves shooting hordes of invading aliens, but the fact that it's mentioned at all shows that this kind of feature was not a given back in the days of arcade games and unrealistic physics. Let's take a look at how it works.

Bullets and velocities

The FireGuns routine is responsible for spawning the game's proudly independent bullets. It calculates the bullet locations as soon as we fire the gun, adding in the bullet trail. As an overhead view, this is what the routine spawns:

    13   ^             ^   15
         |             |
         |      ^      |
         |             |
         |             |
         |             |
         |             |
         |             |
    12   |             |   14

The plane is the ^ in the middle, and each trail consists of two objects. The bullets are at objects 13 and 15, a little in front and to each side of the plane, while the trails go back a long way behind the plane, back to objects 12 and 14. You can't tell from the above diagram, but the trails are also angled upwards as the bullets race away from the place, so objects 12 and 14 have y-coordinates of -4 compared to the plane.

The FireGuns routine calculates the locations of objects 12 to 15, and the line-drawing routines then take care of drawing the bullet lines, the left one from object 12 to 13, and the right one from object 14 to 15.

We also calculate the velocity vector for the bullets, which is used to move the bullets independently once they have been fired; this movement is handled by the UpdateBullets routine that gets called on every iteration of the main loop. We store this vector in points 228 to 231, with one vector for each bullet object (though the value is the same for all four).

We give the bullets a forward velocity of zVelocityPHi + 200, so they travel faster than the plane, but in the same direction (zVelocityPHi is the plane's forward airspeed). The bullet's relative speed is therefore (200 0) faster than the plane, or around 2,162 mph, or 3,170 ft/s (see the commentary around zVelocityPHi for details of the speed variables and what they represent). The Browning .303 Mark II machine gun used in the Spitfire had a muzzle velocity of 2,660 ft/s, so the bullets in Aviator are 20% faster, but as you can only fire one pair of bullets at a time in the game, rather than the 1,150 rounds per minute of the original, the faster speed is welcome.

The spawning calculations

Here's how the bullet's initial positions and velocity are calculated in FireGuns. While reading the steps below, you might find the following diagram might be useful, which shows all the vectors and coordinates we discuss.

                   (xTemp yTemp zTemp)
           13/96   +-------------+   15/98
                   |      ^  plane
                   |     /      
   (0, 0, 256) --> |    /
                   |   /  <-- (-10, -4, -236)
                   |  /
                   | /
           12/95   +-------------+   14/97
                     (20, 0, 0)

The steps are as follows:

  • Calculate the bullet's velocity vector and store in points 228-231:
    • Set point ID 228 to the vector (0, 0, zVelocityPHi + 200)
    • Calculate the 3D coordinates for the vector in point 228, using matrix 2 - this rotates the point from the plane's frame of reference to the outside world's frame of reference, therefore giving us the bullet's velocity vector with reference to the outside world
    • Copy the result into points 229, 230 and 231
  • Set point 95 to (-10, -4, -236), which is the vector from the plane back to object 12:
    • Set point ID 95 to (&FFF6, &FFFC, &FF14) = (-10, -4, -236)
    • Calculate the 3D coordinates for point ID 95, using matrix 2
  • Set objects 12-15 to the location of the plane:
    • Copy the coordinates from (xPlane, yPlane, zPlane) to point 96
    • Set object coordinates for objects 12-15 to point 96
  • Calculate the location of object 12 and set it as the anchor point:
    • Move object 12 by the vector in point 95, i.e. the (-10, -4, -236) vector, so object 12 is now at the correct position
    • Store the result as the anchor point, so the coordinate calculations in the next part will return relative vectors from the plane's location to each point
  • Calculate the vectors from the plane to the other three objects:
    • We now calculate the vectors from the plane to objects 13, 14 and 15, storing those vectors in points 96, 97 and 98
    • We can calculate the vectors for objects 13 and 14 (points 96 and 97) by calling SetObjPointCoords to return as relative vectors from the plane's location. This works as we are telling SetObjPointCoords to take the anchor point vector (which we set above to be the vector from the plane to object 12 at point 95) and add on the vector of the object point (which is the interior vector of the point within the object), which gives us the vector from the plane to the object point

      For reference, the object points are at (0, 0, 256) for point 95 (which we will use for object 13) and (20, 0, 0) for point 96 (which we will use for object 14)

      Calling SetObjPointCoords the second time also sets (xTemp yTemp zTemp) to the vector from point 95 to point 97 (i.e. from object 12 to object 14)
    • We can save doing the same calculation for point 98, as the vector from object 12 to 14 is the same as the vector from object 13 to 15, so we can calculate point 98 by simply adding (xTemp yTemp zTemp) to point 96
  • Move objects 13 to 15 by the calculated vectors:
    • Move object 13 by the vector in point 96
    • Move object 14 by the vector in point 97
    • Move object 15 by the vector in point 98

So that's how "the aircraft bullets, once fired, will continue to move through space in the direction fired, independent of subsequent aircraft manoeuvres". No wonder this was a feature worth noting in the manual... it's pretty involved.