3
\$\begingroup\$

Context

I'm working on making a variant of the atari game Breakaway IV and I'm trying to improve my mouse input handling.

I use the input of a mouse's motion left and right to move the bumper.

public void mouseLocationChanged(Point mouseLocation) {
    if (lastMouseLocation == null) {
        lastMouseLocation = mouseLocation;
        return;
    }
    bumperStep = (int) ((mouseLocation.x - lastMouseLocation.x) * SENSITIVITY_MULTIPLIER);
    lastMouseLocation = mouseLocation;
}

Then in the update method of my game I check if there is a bumper movement queued up.

 public void update() {
    if (inputHandler.isBumperMove()) {
        submitBumperMove(inputHandler.getBumperMove());
    }
    ...
}

If there is, I move the bumper with the below code.

public void submitBumperMove(int move) {
    if (move < -1 * BUMPER_SPEED_LIMIT) {
        move = -1 * BUMPER_SPEED_LIMIT;
    } else if (move > BUMPER_SPEED_LIMIT) {
        move = BUMPER_SPEED_LIMIT;
    }

    testPoint.x = bumper.x + move;
    testPoint.y = bumper.y;

    while (testPoint.x != bumper.x) {
        if (!willCollideWithWall(bumper, testPoint)) {
            bumper.x = bumper.x + move;
            if (bumper.hasBall){
                ball.x = ball.x + move;
            }
        } else {
            move = shrinkStep(move);
            testPoint.x = bumper.x + move;
        }
    }
}

Observed bugs

  1. I don't reset bumperStep with the call to getBumperMove() so the cursor drifts if there isn't a different input to set bumperStep to 0. This mainly happens when the mouse exits the window.
  2. When resetting bumperStep to 0 with getBumperMove() (making it consumeBumperMove()) the mouse can run out of the window before the bumper reaches the edge of the game and the bumper can't be moved to the edge.

Proposed Solution

I was considering resetting the mouse cursor in the center of my window (with the cursor invisible) while the game is in "play" mode with each game update. This would prevent the problem of the mouse leaving the screen and not working while still allowing me to consume the movements which will stop the drifting bumper I'm observing.

Questions(finally ;-) )

  1. Is there a better approach to getting mouse left and right movements from any position in java, or should I stick with just keeping the cursor where I want it?
  2. If locking the cursor is the way to go, how can I pragmatically set the mouse position in Java? I've heard about a Robot class that is supposed to help, but it looked like an application needs special signing/permission to use that.
\$\endgroup\$
2
\$\begingroup\$
  1. If you want to find out the mouse position, even if the mouse is outside of the window, you can use the MouseInfo class of AWT:
int mouse_x = MouseInfo.getPointerInfo().getLocation().x
int mouse_y = MouseInfo.getPointerInfo().getLocation().y

But I would recommend you to fix the position of the mouse inside your window. Otherwise, you will run into another problem, like the mouse will reach the screen border.

Fixing the mouse inside the game window is a common concept to prevent the mouse leaving the screen. A lot of games place it in the middle of the game window, hide it and add an image of a new mouse which shows the in game mouse position while the desktop mouse is kept in the middle. You can see this effect when you tab out of a game and your desktop mouse is visible again. It is mostly placed in the middle of the window instead of the game mouse location.

  1. If you want to force the mouse to a position without any additional native libraries, you can use, as you mention it, the Robot class:
if(myJFrame.isFocused()){
  int mouse_x = myJFrame.getLocation().x + myJFrame.getWidth() / 2;
  int mouse_y = myJFrame.getLocation().y + myJFrame.getHeight() / 2;
  robot.mouseMove(mouse_x, mouse_y);
}

This will place the mouse in the middle of the window and also gives the user the mouse control back if the window gets unfocused. But as you mention also, the Robot class needs on some system special permissions to change the mouse position.

I highly recommend you to use a game library such as LibGDX or at least a native adaptation like LWJGL (which is used by LibGDX) if you want to create a game in Java. Problems like this are easy solved with these libraries.

In LibGDX you can use the setCursorCatched function. It will hide your mouse and fix it in the middle of your window. X and Y coordinates of your mouse are still reported as if the mouse was not caught:

Gdx.input.setCursorCatched(true);

If you want to catch your mouse in the LWJGL library, you can use the following method:

glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
\$\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.