Some background: the basic problem is this: given a starting point and a destination point, make an object move to the destination, accelerating until the object must decellerate to reach the destination at a velocity of zero. This, by itself, is easy. The problem is one-dimensional and it is trivial to convert the solution to apply to a two-dimensional or even a three-dimensional space.
Unforunately things get difficult when you start in a 2D space and add an initial velocity that may be on a vector entirely divergent from the vector to the destination. You have a problem whereby you not only have to accelerate to the target, but you must also negate the object's initial movement away from the target.
The easiest solution is to start off by stopping the object's movement entirely, then accelerating toward the target. This works, but not so well in a game situation. What I want is to perform both of those actions simultaneously.
My solution is to calculate two vectors: the first being the object's current velocity in the direction of the target and the second being how fast the object's path is diverging from the vector to the target. This is best illustrated by the following diagram:
The blue line is the vector (not normalized) toward the destination. The red line is the current velocity vector. The green line partially along the blue line is the componant of velocity in the direction of the target and the green line at a right angle to that is the component of velocity divergent from the target.
Logically, it follows that to move toward the target one must reduce the length of that divergent vector to zero. This is easy: normalize that vector, negate it, and apply a force along it. Similarily, the issue of accelerating toward the target is returned to a one-dimensional problem. Both of these operations can effectively be performed simultaneously, simply by adding the forces resulting from each.
How does once come up with the vectors? As I said: use a dot-product. The dot-product of the normalized velocity and direction-to-target vectors is the cos of the angle between them. What we want are vectors that are at right-angles to each other, so this turns into a right-angled triangle. Some basic trigonometry and some basic Pythagorous and we have both the magnitude of the forward velocity and the divergent velocity. The forward velocity vector is derived by normalizing the vector to the target and multiplying by the forward velocity magnitude.
Unfortunately, finding the vector for the divergent velocity is not so simple. Finding the right angle to a vector is accomplished by negating either the x or y components, depending on the situation. The vector must be on the same side as the initial velocity vector. I. . . ended up with a massive "if" structure:
Code: Select all
if vny > 0:
if dny > 0:
if vnx < dnx:
err = (-dny, dnx)
elif vnx > dnx:
err = (dny, -dnx)
else:
if abs (vny) < abs (dny):
if vnx < dnx:
err = (dny, -dnx)
elif vnx > dnx:
err = (-dny, dnx)
else:
if vnx < dnx:
err = (-dny, dnx)
elif vnx > dnx:
err = (dny, -dnx)
else:
if dny > 0:
if abs (vny) < abs (dny):
if vnx < dnx:
err = (-dny, dnx)
elif vnx > dnx:
err = (dny, -dnx)
else:
if vnx < dnx:
err = (dny, -dnx)
elif vnx > dnx:
err = (-dny, dnx)
else:
if vnx < dnx:
err = (dny, -dnx)
elif vnx > dnx:
err = (-dny, dnx)
I hope the rest of this post helped other who are also interested in this problem.
(After this I need to account for rotation, making it so that the object must turn in order to accelerate in a particular direction -- accounting for angluar velocity, of course. . .)