Some simplifications I failed to mention:
- The algo assumes that the target is moving perpendicularly to the line of sight at initial condition. (Changing the code to fit changes is simple)
- The velocity of the bullet is always assumed to be
1. This is our reference for scales.
- I didn't use vectors since I wanted to look at the essence of the problem. It's easy to transform into and out of this algorithm's space. Divide velocities and distances by the velocity of a bullet. Make the shooter the center of the space, and rotate the whole system such that the line of sight is horizontal and to the right. All these transformations are reversible, so the solution remains general. There is
no necessity that the algorithm works in vector space.
If you only need 5 iterations, why the 50 in your for loop?
The 5, 50, so on are totally nonsense; only for presentation purposes. We need a concrete metric for this algorithm to be useful. It should instead use a halting offset (it gets close by 0.1 mm to the target (electron gun at a mouse's blood cell, or 5Km for a cluster bomb on a moving convoy).
This instruction confuses me. It seems that you're using Pythagoras to determine the position of the impact (!= current position of the target). But in this case doesn't time have a dimension of distance?
Since the velocity of the bullet is
1, distance is numerically equal to time (distance divided by one).
The first iteration assumes that the bullet will hit the target in 0 time (a virtual previous iteration, the initial condition). The distance to the target allows the estimation of the time for the next iteration. Now the bullet is where the object originally was, and the object has moved upwards. The next iteration will aim the bullet to this last position, but the object will have moved. Since the bullet is considerably faster than the object, the object wouldn't have moved much, and as such the offset decreases, and the approximation is getting better. For a considerably fast object (or slow bullet [turpedo vs. yacht]), you would need to check whether the offset is decreasing or increasing. I have yet to see if there are cases where the approximation gets better after getting worse in the iterations, which may make the problem a lot harder.
And what about the recursivity? How is time dependent on its previous value?
In the line you quoted, time's next value is being computed based on its previous value. This code statement defines their relationship (no other lines of code updating time). In fact, you can remove all the other lines in the for loop and still arrive at the correct time. This may in fact help performance as the other values will get computed just once. I do compute them at each step to display offset. We need offset in most cases to see how the algorithm is performing (unless we depend on measuring how much time is changing, and based on that halt).
Following is the more general algorithm that does not assume the perpendicular condition. (There's no transformation that I can think of to translate between the two, so this must be used instead).
private function orient(distX:Number, distY:Number, vel:Number):Number {
var angle:Number = 0;
var time:Number = 0;
var offsetX:Number;
var offsetY:Number;
var offset:Number;
for (var i:int = 0; i < 50; i++) {
time = Math.sqrt(distX * distX + (time * vel + distY) * (time * vel +distY));
angle = Math.atan2(vel * time + distY, distX);
offsetX = (distX - Math.cos(angle) * time);
offsetY = (distY + vel * time - Math.sin(angle) * time);
offset = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
trace(offset);
}
return angle;
}