Reputation: 187
For those of you remembering Descent Freespace it had a nice feature to help you aim at the enemy when shooting non-homing missiles or lasers: it showed a crosshair in front of the ship you chased telling you where to shoot in order to hit the moving target.
I tried using the answer from AI algorithm to "shoot" at a target in a 2d game but it's for 2D so I tried adapting it.
I first decomposed the calculation to solve the intersection point for XoZ plane and saved the x and z coordinates and then solving the intersection point for XoY plane and adding the y coordinate to a final xyz that I then transformed to clipspace and put a texture at those coordinates. But of course it doesn't work as it should or else I wouldn't have posted the question.
From what I notice the after finding x in XoZ plane and the in XoY the x is not the same so something must be wrong.
float a = ENG_Math.sqr(targetVelocity.x) + ENG_Math.sqr(targetVelocity.y) -
ENG_Math.sqr(projectileSpeed);
float b = 2.0f * (targetVelocity.x * targetPos.x +
targetVelocity.y * targetPos.y);
float c = ENG_Math.sqr(targetPos.x) + ENG_Math.sqr(targetPos.y);
ENG_Math.solveQuadraticEquation(a, b, c, collisionTime);
First time targetVelocity.y is actually targetVelocity.z (the same for targetPos) and the second time it's actually targetVelocity.y.
The final position after XoZ is
crossPosition.set(minTime * finalEntityVelocity.x + finalTargetPos4D.x, 0.0f,
minTime * finalEntityVelocity.z + finalTargetPos4D.z);
and after XoY
crossPosition.y = minTime * finalEntityVelocity.y + finalTargetPos4D.y;
Is my approach of separating into 2 planes and calculating any good? Or for 3D there is a whole different approach?
Upvotes: 2
Views: 1001
Reputation: 65854
The equations for the 3D case are the same as I gave in the 2D case. The only difference is that the firing solution isn't in the form of an angle: you need a 3D rotation. But for this application, you don't need a firing solution, you just need to know where to draw the reticule.
For example, taking the simplest case (a stationary shooter which can rotate instantly):
Let the target be at the position A and moving with velocity VA, and the shooter be stationary at the position B and can fire bullets with speed s. Let the shooter fire at time 0. The bullet hits at time t such that |A − B + t VA| = t s. This is a quadratic equation in t, which you should be able to solve (or determine that there is no solution). Having determined t, you can now draw your reticule at the screen position corresponding to the world position where the bullet will hit (which is A + t VA).
The other cases are similar, just as in 2D.
Upvotes: 0
Reputation: 11
If you're at (0,0,0)
at time t_0 = 0
and shoot a projectile with velocity pv
and hit a target that has initial position tp=(tpx,tpy,tpz)
and constant velocity tv=(tvx,tvy,tvz)
at time t, that means that
Abs(tp+t*tv) == t*pv
Solving this equation for t (tp*tv is the scalar product of tp and tv, etc):
t = - (tp*tv ± sqrt((tp*tv)^2+(tp * tp)*(pv^2-tv*tv))) / (tv*tv-pv*pv)
So you need to shoot at the position tp+t*tv
. Just project that into your viewport and draw your crosshair there.
Hope this helps.
Upvotes: 1