Trajectory - hitting target at x/y

Started by
1 comment, last by johnstanp 13 years, 9 months ago
Hello.

I have some AI characters that I want to aim at the player. I'm trying to implement the equation described here:

http://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_.CE.B8_required_to_hit_coordinate_.28x.2Cy.29


For some reason, it's not working. Here's my function:

private float CalculateShooterAngle(){    Vector2 aimingPosition = targetPosition - playerPosition;    float x = aimingPosition.X;    float y = -aimingPosition.Y;    float v2 = v * v;    float v4 = v * v * v * v;    float gx2 = g * x * x;    float tyv2 = 2 * y * v * v;    float gx = g * x;    float sq = v4 - (g * (gx2 + tyv2));    if (sq >= 0.0)    {        float root = (float)Math.Sqrt(sq);        float solution1 = (float)Math.Atan((v2 + root) / gx);        float solution2 = (float)Math.Atan((v2 - root) / gx);        return solution1;    }}


Can anyone see what I'm doing wrong? The angle just doesn't work at all. Sometimes it's close, but no cigar. It seems to get worse the further I move the shooter away from the target. In some quadrants, the shooter's direction seems to flip drastically, pointing straight down. I guess some abrupt angle changes are expected, given that I'm arbitrarily choosing solution1, and throwing away solution2. But no matter what solution is chosen, it's just wrong.

One thing I should mention is that the y-axis is flipped from what you might expect. Since it's an XNA-based 2D sprite game, the y axis points downward, much like it would in a 2D image editing program. So, to shoot at an upward angle, the y-component of my velocity would be negative. However, since my gravity is positive, I figured this would even out and that the above equation should probably work no matter what your coordinate system is. Maybe I'm wrong.

If anyone knows of a place where I can host a 23kb Zip file, I would be happy to post a link to my project. It's pretty self contained, and should be easy to build and run if you have XNA installed.

[Edited by - CDProp on July 1, 2010 1:55:27 AM]
Advertisement
Oh, I should also mention that I'm not using straight Euler integration for the motion of the projectiles. To make it more stable, I calculate the instantaneous velocities each frame (using the simple v += a*t). But instead of using the new instantaneous velocity to calculate the displacement, I first average it with the previous frame's instantaneous velocity. So instead of having this:

vel += acc*time;pos += vel*time;


It looks more like this:

vel += acc*time;pos += (last_vel+vel)*0.5*time;last_vel = vel;
I tried solving your problem with the following system of equations:
x = vx * t (1)
y = vy * t - 1/2 * g * t² (2)
v²= vx² + vy² (3)

(1) => t = x / vx (4)
(4) in (2) => vy² = ( vx * y / x )² + g * y + ( g * x / ( 2 * vx ) )² (5)
(5) in (3) =>
[ 1 + ( y /x )² ]vx² + ( g * x / 2 )²( 1 / vx )² + g * y - v² = 0
<=>[ 1 + ( y /x )² ]vx⁴ + ( g * y - v² )vx² + ( g * x / 2 )² = 0
=> vx² = 0.5 * [ ( v² - g * y ) +- sqrt( v⁴ - 2 * g * v² * y - g² * x² ) ] / [ 1 + ( y / x )² ] (6)

You get rid of the angle the velocity makes with the x axis. (6) gives you two possibles solution for vx. Compute them, and for each of them compute the corresponding vy. Compute the time t with the first equation. And see between the two triples (vx,vy,t) which one verifies the second equation.

[Edited by - johnstanp on July 3, 2010 4:00:10 AM]

This topic is closed to new replies.

Advertisement