0
\$\begingroup\$

I am using the current mouse position to aim the player sprite, but I am not getting the best results.

It will often by off by a noticeable amount, or even a complete ~180 off if I go from one side, through the player, to the other side.

boolean mouseMoved(int screenX, int screenY) {
    mouseX = screenX;mouseY = screenY;
    rot = MathUtils.radiansToDegrees * MathUtils.atan2((float)mouseY - (float)player.y, (float)mouseX - (float)player.x);
    if (rot < 0) rot += 360;
    player.setRot(rot);
}

Update 1:

When I am at 90/270 it seems to pickup the angle fine. But for 0/180, the angle is off depending on how far away my cursor is to a certain point (not the player's point).

Update 2:

Added in semi-fix, but I'm still having the same exact problem

Update 3:

I was mistaken the semi-fix wasn't actually a fix. I fixed it for real, though. The problem was that libgdx has (0,0) at the bottom left, but the InputProcessor has (0,0) at the top left. What I had to do was adjust the mouse position so that it's (0,0) was the bottom left. I did this by

mouseX = screenX;
mouseY = Game.HEIGHT - screen y;

This will give the player coordinates & mouse coordinates the same origin, and then the formula will work.

\$\endgroup\$
  • \$\begingroup\$ 1) Did you make sure player.setRot() take a degrees argument instead of a radian one? 2) You can remove the (float) castings, they will not change anything in your case. 3) How did the rot == 360 semi-fixes the problem? Have you made more test cases with different values? \$\endgroup\$ – Alexandre Desbiens Aug 13 '14 at 1:48
  • \$\begingroup\$ You should put Game.HEIGHT instead of WIDTH if you want the vertical size of the screen... \$\endgroup\$ – Alexandre Desbiens Aug 13 '14 at 17:07
  • \$\begingroup\$ Totally right. I must have just derped when translating. \$\endgroup\$ – Brandon Aug 13 '14 at 17:08
  • \$\begingroup\$ If you answered your own question, feel free to write an answer to your post and mark it as the accepted answer. \$\endgroup\$ – Alexandre Desbiens Aug 13 '14 at 17:10
  • \$\begingroup\$ I posted my answer, hopefully it's enough info to help someone in the same spot. \$\endgroup\$ – Brandon Aug 13 '14 at 17:22
0
\$\begingroup\$

Try multiplying the y value with -1.

And make sure to convert the mouse and playercoordinates to the world coordinates.

I had this exact problem yesterday. It has to do with wrong conversion - think about the two different coordinate-systems (Viewport- and World-coordinates)

\$\endgroup\$
  • \$\begingroup\$ It's fine to suggest things that you're not sure will work or not. However, you should explain what problem your suggestion solves and why you think your suggestion will solve that problem. \$\endgroup\$ – MichaelHouse Aug 12 '14 at 20:43
  • \$\begingroup\$ Sorry I'm on the phone and my answer was fairly short. Extended the answer. \$\endgroup\$ – BrianBrain Aug 12 '14 at 20:45
  • \$\begingroup\$ My word and viewport are the exact same size. \$\endgroup\$ – Brandon Aug 12 '14 at 20:50
0
\$\begingroup\$

Try using different math techniques for the rotation: Instead of degrees, try using Quaternions. It's the most used rotation technique for 3D objects in professional engines, because degrees don't work as well in 3D.

There's more on Wikipedia and I found some Libgdx code.

I have more materials, but I can't include them due to my low reputation, but you can find lots on Google.

\$\endgroup\$
  • 1
    \$\begingroup\$ I'm doing all this in 2d. I'm rotating a polygon, and from what I have seen there isn't an option to use a quaternion \$\endgroup\$ – Brandon Aug 12 '14 at 20:52
0
\$\begingroup\$

First, inverse the player position and the mouse position. This way, you will have the real angle from the player to the mouse, and not the opposite.

Second, atan2 takes the y difference as the first argument, and the x difference as the second. That is probably why your code looks like it fails.

Your code should look like this with the 2 corrections I mentioned:

boolean mouseMoved(int screenX, int screenY) {
    mouseX = screenX;
    mouseY = screenY;
    // Inverted mouse and player position as well as X and Y axis
    float angle = (float)Math.toDegrees(Math.atan2(mouseY - player.y, mouseX - player.x));
    players.setRot(angle);
}

Source: Experience. Here's a link demonstrating the X and Y axis in the atan2 function (notice how Y comes first).

\$\endgroup\$
  • \$\begingroup\$ @Brandon Have you applied any of the fixes I posted? If yes, please update your question. And for the bounty thing, please do not. \$\endgroup\$ – Alexandre Desbiens Aug 12 '14 at 22:47
  • \$\begingroup\$ Ok I will not do that. Yes I did put your fix in, but I'm having the same problem where the degrees are off at the 0 degree and 180 degree (see update 1). \$\endgroup\$ – Brandon Aug 12 '14 at 23:01
0
\$\begingroup\$

The problem was that libgdx has the origin (0,0) in the bottom left corner, but the mouse movement from the InputProcessor has (0,0) in the top left. What I had to do was adjust the mouse y position so that its (0,0) was the bottom left. I did this with:

mouseX = screenX;
mouseY = Game.HEIGHT - screenY;

This will give the player coordinates and mouse coordinates the same origin, and then the formula will work.

Here is the entire working code snippet:

boolean mouseMoved(int screenX, int screenY) {
    mouseX = screenX;
    mouseY = Game.HEIGHT - screenY;
    rot = MathUtils.radiansToDegrees * MathUtils.atan2(mouseY - player.y, mouseX - player.x);
    player.setRot(rot);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.