Jarmund Jarmund - 2 months ago 6x
Java Question

Rewriting so that Math.atan() works regardless of orientation

I have a 2D side-view shooter-thingy that I need some fresh eyes on. I'm currently working on the aiming, and it partially works: muzzle velocity is known, gravity is known, and x,y distance to target is also known. Using various sources both here on SE and wikipedia, I've come up with the following method for calculating starting vector for projectile speed:

public Vector2 calculateAim(Vector2 pos, Unit target) {
// Check if previous calculation can be recycled
if (target.equals(lastTarget))
return lastAim.cpy();
lastTarget = target;

double v = RifleBullet.projectileSpeed; // Muzzle velocity
double g = Settings.gravity.y; // Gravity, positive value
double x = offset.x; // x distance to target. Negative if towards left
double y = offset.y; // y distance to target. Negative if lower

double theta = Math.atan(((v * v) - Math.sqrt((v*v*v*v) - (g*(g*(x*x) + 2*y*(v*v))))) / (g * x));

Vector2 aim = new Vector2(-(float)Math.cos(theta), (float)Math.sin(theta));
lastAim = aim.cpy();
return aim;

The above partially works: The rightmost guy will aim correctly. However, the guy standing to the left is consistently firing in the wrong direction. It looks like the Y component is correct, but the X component is quite simply reversed. If I add this after calculating theta:

if (side.contains("left"))
angleInRadians += Math.PI;

...they both fire correctly, but it's not viable in the long run as there will be more units on the battleground, and it's bound to cause problems when I get to that point.

I believe the source of the problem could be the
function, as I don't have any checks for seeing how the hypothetical triangle in the trigonometry calculation is oriented.

How should I refine my method so that it works properly regardless of who's left/right/up/down?


What Tenfour04 said is quite helpful. You're probably going to want to use Math.atan2(y,x) instead of Math.atan(y/x)

Notice that instead of doing the division yourself, you give the y and x as separate arguments. This is so atan2 knows the difference between things like 5/2 and -5/-2. To normal atan, they both look like 2.5