[SOLVED] Creating "FPS-like" mouse detection

I’m trying to recreate the controls of the game Minecraft. For those who don’t know, when you move the mouse, the direction you’re facing changes accordingly (if you’re moving the mouse upwards, it’s like looking upwards). The thing is, you can move the mouse infinitely in any direction, and it never hits the edge of the screen.
For now, I’m just trying to capture the movement and keep the mouse on the screen. No change of perspective yet.

The code:

import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.AWTException;
import java.awt.Robot;

Robot robot;

Point globalMouse;
boolean manipulateMouse;
PVector mouseMovement;

void setup() {
  size(500, 500);
  
  try {
    robot = new Robot();
  } catch (AWTException e) {
    e.printStackTrace();
    exit();
  }
  
  
  manipulateMouse = false;
  mouseMovement = new PVector();
  
  MouseInfo.getPointerInfo().getLocation();
}

void draw() {
  if (mousePressed) 
    manipulateMouse = true;
  if (keyPressed && key==BACKSPACE) 
    manipulateMouse = false;
  
  if (manipulateMouse) {
    globalMouse = MouseInfo.getPointerInfo().getLocation();
    mouseMovement.set(
      mouseX - (width / 2),
      mouseY - (height / 2)
     );
    robot.mouseMove(
      (int)(globalMouse.x - mouseMovement.x),
      (int)(globalMouse.y - mouseMovement.y)
    );
  } else {
    mouseMovement.set(0, 0);
  }
  
}

What it’s suppose to do:
Each frame, look how much the mouse moved (then store it in the variable mouseMovement), and move it back to the center of the window, using the awt.Robot library.

What it actually does:
When you start moving the mouse, it doesn’t return it to the center, but starts a weird back-and-forth or circular movement.

Is it a problem with my calculation? A floating point thing? How do I fix it?

Thanks in advance :slight_smile:

P.S
Messing with user inputs is dangerous, so it only activates when you click the window, and stops if you hit BACKSPACE.

3 Likes

Hey There!

Huh Interesting. Maybe you should calculate where the mouse has moved and put it in the middle only when you stop moving the mouse.

Maybe you should calculate where the mouse has moved and put it in the middle only when you stop moving the mouse.

But if you move the mouse continuesly to the edge, it will still hit it…

Found out the problem: MouseInfo.getPointerInfo().getLocation() gets updated long after mouseX, mouseY are (and it had nothing to do with the order I call them in). So when I try to compare them while in motion, their differences are inconsistent.
Basically, I need a consistent way to find out the location of the sketch on the screen.
Tried to use frame.getLocationOnScreen(), but it told me so: IllegalComponentStateException: component must be showing on the screen to determine its location (I made sure the function is called only when the sketch is in focus).
So now I’m more confused than before.

There is also this blog post, which solved the very problem I’m working on, but it doesn’t work anymore / in my computer, because f backwards and platform compatibility, amiright?

SOLVED!!!

All you need to do to calculate the window location, is to compare mouseX,mouseY to MouseInfo.getPointerInfo().getLocation(), only when I know for sure that the mouse didn’t move / moved very little since the system got all input events. And what’s a better way of doing it than the function mouseClicked()?
Heres the final, fixed, working code.
Note: if you intentionally try to trick it, you’ll be able to offset it by a few tens of pixels. No big deal on a big enough scene.

import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.AWTException;
import java.awt.Robot;

Robot robot;

boolean manipulateMouse;
PVector windowOffset;
PVector mouseMovement;

void setup() {
  size(500, 500);
  
  try {
    robot = new Robot();
  } catch (AWTException e) {
    e.printStackTrace();
    exit();
  }
  
  manipulateMouse = false;
  windowOffset = new PVector();
  mouseMovement = new PVector();
}

void mouseClicked() {
  Point globalMouse = MouseInfo.getPointerInfo().getLocation();
  windowOffset.set(globalMouse.x - mouseX, globalMouse.y - mouseY);
  manipulateMouse = true;
}

void draw() {
  if (keyPressed && key==BACKSPACE) 
    manipulateMouse = false;
  
  if (manipulateMouse) {
    mouseMovement.set(
      mouseX - (width / 2),
      mouseY - (height / 2)
     );
    robot.mouseMove(
      (int)(windowOffset.x + (width / 2)),
      (int)(windowOffset.y + (height / 2))
    );
  } else {
    mouseMovement.set(0, 0);
  }
  
}
2 Likes