0
\$\begingroup\$

I'm starting with a screen resolution of 1280 x 960 and that is the default resolution where mouse aiming is calculated thus:

angleRad = (float) (Math.atan2(screenX - (screenWidth / 2), screenY - (screenHeight / 2)));
angle = (float) Math.toDegrees(angleRad - Math.PI / 2);
angle = Math.round(angle) <= 0 ? angle += 360 : angle;
if (Math.round(angle) == 360)
    angle = 0;

Which all works fine. But when the game is resized to some resolution with a vastly different ratio to the default, like for example 2560 x 1440 at full screen in my case, the aiming is off. The resize method is like this:

@Override
public void resize(int width, int height) {
    game.getViewport().update(width, height);
    control.screenWidth = width;
    control.screenHeight = height;
}

Where control.screenWidth and control.screenHeight are used in the above angle calculation and as the set resolution in other areas. The angle calculation when resized is roughly correct but tends to get further and further off course the further the aim is away from the player.

If the player aims straight up, down, left or right (N, S, W or E basically) then the aim is dead on, but veers off as aiming goes away from the player towards a screen edge - no doubt due to the resolution ratio difference.

We have these ratio differences which no doubt affect the angle calculation:

1280x960 1.33 ratio
2560x1440 1.77 ratio

But I'm not sure how to take into account these ratios to adjust the angle calculation accordingly in my code?

The crosshair and bullets are both off position. In the screenshot below the crosshair position in comparison with the mouse pointer can be seen. This is for resolution 2560x1440. The code for the crosshair is this:

point = angleToVector((float) (angleRad + Math.PI)).scl(10000);
gs.getWorld().rayCast(callBack, pos, point);

angleRad is the mouse angle in radians, pos is the vector position of the player and point is the vector target position. This is the raycast callback

private RayCastCallback callBack = new RayCastCallback() {
    @Override
    public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) {
            collision.set(point);
        return fraction;
};

enter image description here

\$\endgroup\$
5
  • \$\begingroup\$ Your angle calculation looks correct, though I'm confused why you would use angles here at all. A direction vector is simpler to calculate and use, with no trigonometry needed to encode/decode it. Can you show us the numbers you're getting for screenX and screenY for a particular problem case where the aim is off, what angle you get out, and what angle you expect instead? A screenshot of your game would help too - I'm assuming you're using a top-down view, but if you have an oblique or isometric view that could change things. \$\endgroup\$ – DMGregory Aug 25 '20 at 14:05
  • \$\begingroup\$ @DMGregory♦ A direction vector is better for mouse aiming? I thought it was normally done with angles. screenX and screenY give a number between 0 and the currently sized screen height or width with screenY 0 being the top of the screen. I forgot to mention I have an aim crosshair displaying on the screen too. \$\endgroup\$ – Hasen Aug 25 '20 at 15:02
  • \$\begingroup\$ My general advice is to avoid angles like the plague absolutely any time that you can. ;) But I wasn't asking for the range of the variables, I was asking for a test case. Something of the form "Here is a screenshot where this code behaves incorrectly. On this frame, screenX is 42 and screenY is 49, the computed angle is X, but I think it should be Y instead" \$\endgroup\$ – DMGregory Aug 25 '20 at 15:14
  • \$\begingroup\$ When you crop your code down to tiny snippets like this, you hide information we need to be able to help you. Here, we can't see how pos is defined. I would strongly recommend (again) that you edit your question to include a Minimal Complete Verifiable Example. That is: every step that we would need to reproduce this problem in a new project. Once we can reproduce the problem, we can test potential fixes to be sure they'll work for you. \$\endgroup\$ – DMGregory Aug 25 '20 at 16:21
  • \$\begingroup\$ DMGregory♦ Strange I meant to write that pos was the player position etc but somehow left it. It's all there now. \$\endgroup\$ – Hasen Aug 25 '20 at 16:25
0
\$\begingroup\$

Here "point" is actually an offset vector (a relative shift in space, with a direction and distance).

point = angleToVector((float) (angleRad + Math.PI)).scl(10000);

Here "point" is being used as a position (an absolute location in space).

gs.getWorld().rayCast(callBack, pos, point);

So you're drawing your ray from the player position, pos, to a point 10000 units in your aiming direction measured from the world origin.

It looks to me like you want:

point = pos.cpy().add(angleToVector((float) (angleRad + Math.PI)).scl(10000));

to aim from the player position, not from the world origin.

\$\endgroup\$
15
  • \$\begingroup\$ This point = pos.add(angleToVec((float) (angleRad + Math.PI))); makes the program quit with error Assertion failed: (r.LengthSquared() > 0.0f), function RayCast, file ./Box2D/Collision/b2DynamicTree.h, line 209.. With or without the scaling by 10,000 it quits the same way. Might be you're onto something but I've no idea why it's throwing this error. \$\endgroup\$ – Hasen Aug 25 '20 at 16:50
  • \$\begingroup\$ Right because as the documentation states, Vector2.add works by "returning a reference to itself" - ie. you haven't copied pos with that line, you've modified pos. So now point and pos point to the same vector and you're trying to cast a ray from a point to itself (zero length). You probably want to copy the vector first as shown in the edit above. \$\endgroup\$ – DMGregory Aug 25 '20 at 16:55
  • \$\begingroup\$ DMGregory♦ Ah ok interesting, I'll make a note of that since I think I've had that error before and Java error messages don't tell you a lot. But strangely doing it this way is exactly the same as the original way with the same issue....for some reason there's no difference in the mouse cursor and crosshair position. I added a shaperrenderer line in drawing from the player to the point to make it clearer too. \$\endgroup\$ – Hasen Aug 25 '20 at 17:02
  • \$\begingroup\$ I'd be interested in seeing updated test cases in your question, showing that line and the values you're getting in your key variables along the way. \$\endgroup\$ – DMGregory Aug 25 '20 at 17:04
  • \$\begingroup\$ Something else to troubleshoot: is your mapping of physics coordinates to screen pixel coordinates affected by aspect ratio? If you place a circle in your physics world, does it behave like an ellipse when you make your screen wider? \$\endgroup\$ – DMGregory Aug 25 '20 at 17:09

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.