Basic Dogfight Mode (2): Pure Positional Spring Theory

The next thing I tried to do to make one plane follow another was to base its movement off the same sort of movement a chase camera does. It didn't turn out as expected, though.

Previous Post:
Basic Dogfight Mode (1): Basic Yaw/Pitch Adjustments - Memories of Melon Pan

A basic chase camera can behave like a spring system. It's a classic mechanical system - just imagine a regular spring hanging from a ceiling with a dense wooden cube at the end to act as a weight. You pull down on the weight, let go, and what happens? Yup, the spring goes up and down, up and down, mesmerizing the minds of children everywhere until it finally stops where it started.

The position where the spring naturally rests we call the equilibrium position. The system also has a host of other variables as well - the spring moves so it has speed and position, the weight has mass, the spring has springiness or stiffness (yes, this can be reduced to a number), and so on. How are these all related?

By the power of MATH!

f = m * A = (-k * (X0 - Xz)) - (c * V0)


For the variables:

  • f, force, a three dimensional vector
  • m, mass, a scalar value
  • A, acceleration, an unknown three dimensional vector
  • k, the spring constant, a scalar value
  • X0, most recent position, a three dimensional vector
  • Xz, the target position, a three dimensional vector
  • c, the damping coefficient, a scalar value
  • V0, most recent velocity, a three dimensional vector

We're kinda taking the one dimensional spring and applying it in three dimensions when we make our chase camera here - we don't want to go just up and down, but also left, right, towards, and backwards. The intuitive thing to do is to use vectors for a lot of the variables here, and that'll do us. We know position has to be a three dimensional value, but we can have things like velocity and acceleration as three dimensional vectors as well, each with a component for the x, y, and z axes.

You probably noticed I talked about the equilibrium distance (which in three dimensional space is an equilibrium vector) but I only mentioned target position in the formula. Every time we use a position in the equation, we're talking about world space, so we have to find out at what point in world space the spring naturally rests at. If the spring comes to equilibrium (25, 25, 0) from its base, and its base is at (200, 200, 1000), then we can add those together and see that the spring wants to stand still at (225, 225, 1000) in world space. And for a chase camera, the base of the spring is whatever the camera's chasing.

Xz = Xt + Xe


For the variables:

  • Xz, the target position
  • Xt, the position of the chase target
  • Xe, the equilibrium vector

So back to our force formula, you can just muck with values for mass, spring constant, equilibrium vector, and damping coefficient to make the spring behave the way you want it to.

Ultimately, we want to update the position of the chase camera to some new position, and we have one unknown: acceleration. Just plug in the last position and velocity of the ship into X0 and V0, and divide the right side of the equation by mass. You'll end up with the acceleration of the ship at this frame.

And what do we know about acceleration?

V = A * t
X = V * t


For the variables:

  • X, position
  • V, velocity
  • A, acceleration
  • t, time

Using the amount of time elapsed between each frame (ideally 16.66 ms, if you're running at 60 frames per second) as t, we can calculate the new velocity, and then the new position of our chase camera.

This is the basics of a chase camera, and the last step is just pointing it either directly at your chase target, or at some offset from it. It's pretty simple, so I'm going to skip ahead and ask: instead of having a chase camera and target ship, what if we have a chase ship and a target ship?

That was what I was thinking as soon as I programmed a chase camera myself, but let's just say that if your ships have infinite maneuverability, it'll look okay... sometimes.

When I did my test run, I changed the target position so that the chasing ship would try to maintain some distance between it and the target.

Xz = Xt + (De * normalize(Xs - Xt))


For the variables:

  • Xz, the target position
  • Xt, the position of the target ship
  • De, the equilibrium distance, a scalar value
  • Xs, the position of the chasing ship

Where normalize(v) converts a vector v to its normalized form.

Then I just pointed the ship in the direction of the chase target, and for fun I gave it the same up vector so that the two ships would roll together.

But put it all together, and what did I find?

... Well, dang. If the chasing ship gets too close to its target, it will start to move backwards. This means if the two are heading right towards each other, eventually the chasing ship will moonwalk backwards in order to bring itself back to its equilibrium distance. It should be obvious, but normal planes can't do this.

Thing is, when we're moving the ship around like this, we're not moving it around like a ship. It can have negative acceleration, or even acceleration that lets it slide left and right. This means that we eventually figure out some position in space the plane should be in and place it there, ignoring things like flight physics and stuff. We're also pointing it towards the its target so it can yaw and pitch as fast as it wants.

So if we want to use spring forces to yank the chasing ship around, we have to make sure that none of these get out of hand. We could make sure the new acceleration doesn't change the ship's heading too much, and keep it from pulling those slidey stunts. What I did in the end, though, was change what these spring forces were acting on, though I when I did that, it turned out to be a mix between this and simple braindead DFM.

Next Post:
Basic Dogfight Mode (3): Yaw/Pitch/Throttle Spring Theory - Memories of Melon Pan