Parabolic motion

I worked on the motion code for the Sky Commando tonight. Originally I calculated his starting velocity and acceleration from the usual equation for a parabola, with the origin located at the player’s crosshair and a starting reference point at x = -crosshairLocation.X. The idea was to get the Commando to swoop in from the side of the screen and cross right through the middle of the crosshair.

Instead, the commando kept swooping in just above it. I decided I should scale the motion updates by the amount of time elapsed since the previous update, but the framerate is pretty much dead on at 60fps, so that made no real difference other than to affect the speed of all the objects on-screen.

After playing with it for a while, I realized the Commando was reaching the x-coordinate of the crosshair before the y-coordinate. I had his X velocity locked at ‘2’, and changing it to ‘1’ made everything to work. I should have realized this sooner–that the way I was computing his y-velocity and acceleration was assuming a unit x-velocity (and zero x-acceleration).

However, this still wasn’t quite what I wanted. I could scale the velocity and acceleration correctly to still achieve the crosshair interception, but if the crosshair was at the left side of the screen, the commando swooped in much too quickly (because of the steep derivative of such a narrow parabola). So I changed things around to compute the angle of the parabola’s derivative at the Commando’s starting point, then scale that to a unit vector and apply a constant “commando speed” to that unit vector to achieve constant total speed in whatever direction the Commando flew.

But there was one more problem: now the acceleration was again off. It assumed either a unit X-velocity or one scaled by a constant–not one that depends on an arbitrary launch angle.

The solution to this problem is really satisfying: because there’s zero acceleration in the x direction (because we neglect air resistance), the Commando will always reach the x-coordinate of the crosshair in (crosshairLocation / x-velocity) time units. That means if we want him to also correctly close the y-distance (which he’d have to in order to fly through the middle of the crosshair and not above or below it), his y-acceleration should be whatever value causes his y-velocity to reach 0 in (crosshairLocation / x-velocity) time steps.  This isn’t totally intuitive, but if we examine the parameterized equation for velocity (in just the y dimension):

v = v0 + at

and then solve it for a:

a = (v – v0) / t

we see we can compute any acceleration we want, given a starting velocity v0, a target velocity v, and a time quantity t. Well, v0 is just the y-velocity computed at the start of the Commando’s trajectory (which happens to be commandoSpeed * sin(launch angle)), and t is (crosshairLocation / x-velocity). So what is the target velocity v? Since we want the Commando to reach the crosshair right at the bottom of the parabola, the target velocity v (which, remember, is the y-velocity) is 0. So we put these values into the equation and compute our acceleration a, and that acceleration causes the Commando’s y-velocity to decrease to 0 at time t, which is also when he reaches the x-coordinate of the crosshair.  If his y-velocity is 0, he must be at the bottom of the parabola, which also happens to be the location of the crosshair as defined in the first paragraph.

Once the Commando reaches the crosshair, the code clamps his y-velocity to 0 so he can just cruise at a constant altitude. I’ll probably ultimately have him deploy a parachute or something.

Leave a Reply

Your email address will not be published. Required fields are marked *