Suppose you have:
Starting postiton: (x0,y0)
Ending position: (x1,y1)
Velocity: v
Elapsed time: t
Then compute your hypontenuse *once*; i.e., when you compute the
destination position, and velocity, also compute the hypontenuse
between the two points. So you can assume you also have:
Hypotenuse: h = sqrt( (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1) );
Then for a given elapsed time (since your sprite was at its starting
point) you get the current position (x,y) as:
x = x0 + ((x1-x0) * v * t) / h;
y = y0 + ((y1-y0) * v * t) / h;
Once (t * v) has equalled or exceeded h, you know that the sprite has
reached or exceeded its end point. As a simple optimization you can
precompute (x1-x0) and (y1-y0).
Simple physics. For accuracy reasons its important to maintain the
old (x0,y0) as well as the target (x1,y1) (or (x1-x0,y1-y0) which
would be equivalent), the variables v,t and h should be floating
point values and the equations given above should be computed with
the give order of operations. This will allow you to maintain
x,y,x0,y0,x1,y1 as integers if you wish.
If you use floating point variables only, you can relax the order of
operation requirements and precompute (v/h) beforehand. This would
also allow you to drop the values of (x0,y0) and use an incremental
approach (using delta t, rather than t since starting) but then the
end detection strategy has to change.
The advantage of the floating point method is that you can avoid an
extra divide (which is nasty) and you have the opportunity to use the
FPU for calculations. The disadvantage is that most graphics
libraries prefer to receive integer coordinates, hence a conversion
is required.
Changing motion should be acheived by changing "v" and/or (x1,y1) in
an AI, or player update phase of your application. However if your
goal is to take gravity into account then you might proceed as
follows:
Suppose you have:
Starting height: z0
Starting Velocity: v0
Acceleration constant: a
Absolute terminal velocity: vt
Elapsed time: t
Here everything is considered in floating point notation. Then the
new height and velocity would be computed as:
z = (a/2)*(t * t) + (v0 * t) + z0
v = v0 + (a * t)
The velocity "v" is ordinarily clamped by the "terminal velocity"
beyond which the velocity can never go above or below. Once the
velocity reaches "terminal velocity" (i.e., abs(v0)>=vt) the height
should be updated linearly as follows:
z = (v0 * t) + z0
If the update causes the velocity to go from non-terminal to
terminal (abs(v0 + a * t)>=vt>abs(vo)) then for complete accuracy you
should compute the update in two parts by first calculating the two
time intervals t0 and (t-t0) according to:
t0 = (vt*sgn(v0 + (a * t)) - v0)/a
Then iterate the two updating formulae above in order according to
z0 <- z and v0 <- v first with t <- t0 then with t <- (t-t0).
sgn is a function returning 1, 0, -1 depending on the sign of the
argument, such that x == abs(x)*sgn(x).
Note that it makes little sense to perform these computations in
more than one axis at a time. You should orient your Z-axis to
point towards the center of gravity. If this is not possible then
you end up with an acceleration and velocity vector, rather than
constants above.
If you have more than one gravitational force, then you have to use
an "n-body" solutions to the problem. There is a well known
approximation method that uses differences on the taylor expansion
of the motion path vectors which acheives accuracy on the order of
the fourth derivative multiplied by a smallish factor.
Copyright © 1996, Paul Hsieh All Rights Reserved.