Reputation: 141
I'm making a 2D topdown view shooter game with Java Swing. I want to calculate what angle the mouse pointer is compared to the center of the screen so some of my Sprites can look toward the pointer and so that I can create projectiles described by an angle and a speed. Additionally If the pointer is straight above the middle of the screen, I want my angle to be 0°, if straight to its right, 90°, if straight below 180°, and straight left 270°.
I have made a function to calculate this:
public static float calculateMouseToPlayerAngle(float x, float y){
float mouseX = (float) MouseInfo.getPointerInfo().getLocation().getX();
float mouseY = (float)MouseInfo.getPointerInfo().getLocation().getY();
float hypotenuse = (float) Point2D.distance(mouseX, mouseY, x, y);
return (float)(Math.acos(Math.abs(mouseY-y)/hypotenuse)*(180/Math.PI));
}
The idea behind it is that I calculate the length of the hypotenuse then the length of the side opposite of the angle in question. The fraction of the 2 should be a cos
of my angle, so taking that result's arc cos
then multiplying that by 180/Pi should give me the angle in degrees. This does work for above and to the right, but straight below returns 0 and straight left returns 90. That means that I currently have 2 problems where the domain of my output is only [0,90] instead of [0,360) and that it's mirrored through the y (height) axis. Where did I screw up?
Upvotes: 0
Views: 561
Reputation: 40047
You can do it like this.
500x500
, top left being at point 0,0
and bottom right being at 500,500
.Y
over the change in X
of two points. Also known as the slope it is the ratio of the sin
to cos
of a specific angle. To find that angle, the arctan
(Math.atan
or Math.atan2
) can be used. The second method takes two arguments and is used below.BiFunction<Point2D, Point2D, Double> angle = (c,
m) -> (Math.toDegrees(Math.atan2(c.getY() - m.getY(),
c.getX() - m.getX())) + 270)%360;
BiFunction<Point2D, Point2D, Double> distance = (c,
m) -> Math.hypot(c.getY() - m.getY(),
c.getX() - m.getX());
int screenWidth = 500;
int screenHeight = 500;
int ctrY = screenHeight/2;
int ctrX = screenWidth/2;
Point2D center = new Point2D.Double(ctrX,ctrY );
Point2D mouse = new Point2D.Double(ctrX, ctrY-100);
double straightAbove = angle.apply(center, mouse);
System.out.println("StraightAbove: " + straightAbove);
mouse = new Point2D.Double(ctrX+100, ctrY);
double straightRight = angle.apply(center, mouse);
System.out.println("StraightRight: " + straightRight);
mouse = new Point2D.Double(ctrX, ctrY+100);
double straightBelow = angle.apply(center, mouse);
System.out.println("StraightBelow: " + straightBelow);
mouse = new Point2D.Double(ctrX-100, ctrY);
double straightLeft = angle.apply(center, mouse);
System.out.println("Straightleft: " + straightLeft);
prints
StraightAbove: 0.0
StraightRight: 90.0
StraightBelow: 180.0
Straightleft: 270.0
I converted the radian output from Math.atan2
to degrees. For your application it may be more convenient to leave them in radians.
Here is a similar Function
to find the distance using Math.hypot
BiFunction<Point2D, Point2D, Double> distance = (c,m) ->
Math.hypot(c.getY() - m.getY(),
c.getX() - m.getX());
Upvotes: 1