Extend mouseX position beyond screen

As the topic states, I need to be able to move my mouseX “outside” of the screen, as if my screen was endless. I need it to be able to endlessly rotate a box on the x axis. The cursor should not leave the screen at any point, and can not be confined to center, as this will mess up the rotating.

int grid = 100;
PVector bpos = new PVector();
float bsize = grid;
float bspeedX, bspeedY, bspeedZ;
boolean input1, input2, input3, input4;
float cameraRotateX;
float cameraRotateY;
float cameraSpeed;
int gridCount = 50;
PVector pos, speed;
float accelMag;

void setup() {
  fullScreen(P3D);
  cameraSpeed = TWO_PI / width;
  cameraRotateY = -PI/6;
  pos = new PVector();
  speed = new PVector();
  accelMag = 2;
}

void draw() {
  lights();
  translate(width/2, height/10);
  rotateX(cameraRotateY);
  rotateY(cameraRotateX);
  background(125); 
  pushMatrix();
  translate(bpos.x, height/2 + bpos.y, bpos.z);
  stroke(255);
  fill(0);
  rotateY(atan2(speed.x, speed.y));
  box(bsize);
  popMatrix();

  PVector accel = getMovementDir().rotate(cameraRotateX).mult(accelMag);
  speed.add(accel);
  pos.add(speed);
  speed.mult(0.9);  
  translate(0, height/2+bsize/2);
  drawGrid(gridCount);
}

void drawGrid(int count) {
  translate(-pos.x, 0, -pos.y);
  stroke(255);
  float size = (count -1) * bsize*2;
  for (int i = 0; i < count; i++) {
    float pos = map(i, 0, count-1, -0.5 * size, 0.5 * size);
    line(pos, 0, -size/2, pos, 0, size/2);
    line(-size/2, 0, pos, size/2, 0, pos);
  }
}

void mouseClicked()
{
  println("bpos.x" + bpos.x);
  println("bpos.y" + bpos.y);
  println("bpos.z" + bpos.z);
  
  println("X" + mouseX);
  println("Y" + mouseY);
}

void mouseMoved() {
  cameraRotateX += (mouseX - pmouseX) * cameraSpeed;
  cameraRotateY += (pmouseY - mouseY) * cameraSpeed;
  cameraRotateY = constrain(cameraRotateY, -HALF_PI, 0);
}

PVector getMovementDir() {
  return pressedDir.copy().normalize();
}

boolean wPressed, sPressed, aPressed, dPressed;
PVector pressedDir = new PVector();

void keyPressed() {
  switch(key) {
  case 'w':
    wPressed = true;
    pressedDir.y = -1;
    break;
  case 's':
    sPressed = true;
    pressedDir.y = 1;
    break;
  case 'a':
    aPressed = true;
    pressedDir.x = -1;
    break;
  case 'd':
    dPressed = true;
    pressedDir.x = 1;
    break;
  }
}

void keyReleased() {
  switch(key) {
  case 'w':
    wPressed = false;
    pressedDir.y = sPressed ? 1 : 0;
    break;
  case 's':
    sPressed = false;
    pressedDir.y = wPressed ? -1 : 0;
    break;
  case 'a':
    aPressed = false;
    pressedDir.x = dPressed ? 1 : 0;
    break;
  case 'd':
    dPressed = false;
    pressedDir.x = aPressed ? -1 : 0;
    break;
  }
}

Feel free to ask questions.

1 Like

Since your sketch is already full screen I don’t see how you can extend the mouseX position, surely it is limited by the OS to the screen dimensions.

I think he needs robot to constrain the mouse to the screen?

Aghh I think I know what he means - back in a sec.

Can’t use the mouseMoved method because once the mouse reaches the left / right display edges any mouse move events will be for the y axis value only.

You need to base the X rotation on the mouse X position so perhaps in the middle 70% no rotation only rotate if the moseX is in the 15% either side of the display. Or something along those lines. the 15% on each side the camera speed

Not needed! I got the program working by constraining the mouse to the center after all! I can post the final code if you’re interested?

1 Like

I am interested

:wink:

Chrisir

@Chrisir Here’s the code! :slight_smile:

import java.awt.*;
Robot robot;

int grid = 100;
PVector bpos = new PVector();
float bsize = grid;
float bspeedX, bspeedY, bspeedZ;
boolean input1, input2, input3, input4;
float cameraRotateX;
float cameraRotateY;
float cameraSpeed;
int gridCount = 50;
PVector pos, speed;
float accelMag;
float gravity=0.3;

void setup() {
  fullScreen(P3D);
  smooth();
  cameraSpeed = TWO_PI / width;
  cameraRotateY = -PI/6;
  pos = new PVector();
  speed = new PVector();
  accelMag = 2;
  try {
    robot = new Robot();
  } 
  catch(Exception ex) {
    println(ex);
  }
}

float angle;

void draw() {
  updateRotation();
  lights();
  translate(width/2, height/10);
  rotateX(cameraRotateY);
  rotateY(cameraRotateX);
  background(125); 
  pushMatrix();
  translate(bpos.x, height/2 + bpos.y, bpos.z);
  stroke(255);
  fill(0);
  rotateY(atan2(speed.x, speed.y));
  box(bsize);
  popMatrix();

  PVector accel = getMovementDir().rotate(cameraRotateX).mult(accelMag);
  speed.add(accel);
  pos.add(speed);
  speed.mult(0.9);  
  translate(0, height/2+bsize/2);
  drawGrid(gridCount);
  noCursor();

  angle += mouseChangeX()*0.003;
  robot.mouseMove(getSketchCenterX(), getSketchCenterY());
}

void drawGrid(int count) {
  translate(-pos.x, 0, -pos.y);
  stroke(255);
  float size = (count -1) * bsize*2;
  for (int i = 0; i < count; i++) {
    float pos = map(i, 0, count-1, -0.5 * size, 0.5 * size);
    line(pos, 0, -size/2, pos, 0, size/2);
    line(-size/2, 0, pos, size/2, 0, pos);
  }
}

void mouseClicked() //only used so I can keep track of coordinates in case I need to change things
{
  println("bpos.x" + bpos.x);
  println("bpos.y" + bpos.y);
  println("bpos.z" + bpos.z);

  println("X" + mouseX);
  println("Y" + mouseY);
}

  int getSketchCenterX() {
    return getFrame(getSurface()).getX() + width / 2;
  }
  
  int getSketchCenterY() {
    return getFrame(getSurface()).getY() + height / 2;
  }
  
  static final com.jogamp.newt.opengl.GLWindow getFrame(final PSurface surface) {
    return ((com.jogamp.newt.opengl.GLWindow) surface.getNative());
  }
  
  float mouseChangeX() {
    return getSketchCenterX() - (float) MouseInfo.getPointerInfo().getLocation().getX();
  }
  
  float mouseChangeY() {
    return getSketchCenterY() - (float) MouseInfo.getPointerInfo().getLocation().getY();
  }
  
void updateRotation() {
  cameraRotateX -= mouseChangeX() * cameraSpeed;
  cameraRotateY += mouseChangeY() * cameraSpeed;
  cameraRotateY = constrain(cameraRotateY, -HALF_PI, 0);
}

PVector getMovementDir() {
  return pressedDir.copy().normalize();
}

boolean wPressed, sPressed, aPressed, dPressed;
PVector pressedDir = new PVector();

void keyPressed() {
  switch(key) {
  case 'w':
    wPressed = true;
    pressedDir.y = -1;
    break;
  case 's':
    sPressed = true;
    pressedDir.y = 1;
    break;
  case 'a':
    aPressed = true;
    pressedDir.x = -1;
    break;
  case 'd':
    dPressed = true;
    pressedDir.x = 1;
    break;
  }
}

void keyReleased() {
  switch(key) {
  case 'w':
    wPressed = false;
    pressedDir.y = sPressed ? 1 : 0;
    break;
  case 's':
    sPressed = false;
    pressedDir.y = wPressed ? -1 : 0;
    break;
  case 'a':
    aPressed = false;
    pressedDir.x = dPressed ? 1 : 0;
    break;
  case 'd':
    dPressed = false;
    pressedDir.x = aPressed ? -1 : 0;
    break;
  }
}

4 Likes

Thank you so much!!!

Thanks for that.

Worked on it and the player can now jump also.

It would be nice if you would use a player and camera class to capsule the code.

Can you explain a bit about how it works?

Warm regards

Chrisir

Oh that sounds wonderful! Will you be able to send the code to me? I have added a sprint-function to it, although it needs refining.

Classing the code will be on my todo list. :wink:
Also, explain the code in general, or this problem specifically?

In general

Thank you

Chrisir

As some parts of the code has been written with the help of a friend, I do not exactly know what those parts of it do, although I get the general idea behind it.

We start by creating some global variables, and I can tell you that float bspeedX[...] and boolean input1[...] is not used. The float gravity=0.3; is not used either.

The cameraSpeed and cameraRotateY in setup() is used to set, of course the speed and rotation. Without those, the camera function wouldn’t work.
The try { robot = new Robot();} is used later in the code, for the camera function.
In draw() the box is drawn, speed, position and acceleration is created, as well as initializing the robot function for the camera. In draw() we also create several voids, one of them being the drawGrid(gridCount); gridCount was created as a global variable.
void drawGrid is pretty self explanatory, it is used to create the grid, by drawing lines.
From int getSketchCenterX() to void updateRotation() we create the camera function. The general idea is there, although I am afraid I can’t quite explain this part. I would like to guess that it constrains the mouse, stores the location and updates the camera according to the location changes of the mouse. The robot function is used here as well.

We move down to the movement, which was also not written by me. The movement works as it should, although I would like it to be different. void keyPressed() registers the keys pressed, and updates the pressedDir accordingly. I would like to believe that this is used in PVector getMovementDir() and then used in the draw() PVector function (PVector accel) to update the movement.
The boolean w,s,a,dPressed is used to help keep track of what keys are pressed, and later used in keyReleased to figure out if the user already is moving in the opposite direction of what the user is now pressing (user presses ‘s’, is user already pressing ‘w’?)

That should be a rough explanation of the code, how crude it might be. My apologies for not being able to explain it better. Now, about the code you have written, with the jump function, would you be able to send it to me?

2 Likes

Thank you so much!

Here is a version with a player class and a jump (Space Bar).

Chrisir



import java.awt.*;

Robot robot;

float cameraRotateX;
float cameraRotateY;
float cameraSpeed;

float angle;

boolean wPressed, sPressed, aPressed, dPressed;
PVector pressedDir = new PVector();

Player player; 

com.jogamp.newt.opengl.GLWindow myGLWindow;

float gridLevelY; 

// ----------------------------------------------------------------------------------------

void setup() {
  // fullScreen(P3D);
  size (800, 800, P3D);

  smooth();

  myGLWindow=getFrame(getSurface());

  player = new Player(); 

  gridLevelY = height/2+player.bsize/2; 

  cameraSpeed = TWO_PI / width;
  cameraRotateY = -PI/6;

  try {
    robot = new Robot();
  } 
  catch(Exception ex) {
    println(ex);
  }

  noCursor();
}

void draw() {
  background(125);
  lights();

  updateRotation();

  translate(width/2, height/10);
  rotateX(cameraRotateY);
  rotateY(cameraRotateX);

  player.jumpManagement(); 
  player.display(); 
  player.move();

  drawGrid();

  angle += mouseChangeX()*0.003;
  robot.mouseMove(getSketchCenterX(), getSketchCenterY());
}

// -----------------------------------------------------------------

void drawGrid() {
  int count = 50;
  translate(-player.pos.x, 
    gridLevelY, 
    -player.pos.y);
  stroke(255, 0, 0);
  float size = (count -1) * player.bsize*2;
  for (int i = 0; i < count; i++) {
    float pos2 = map(i, 0, count-1, -0.5 * size, 0.5 * size);
    line(pos2, 0, -size/2, pos2, 0, size/2);
    line(-size/2, 0, pos2, size/2, 0, pos2);
  }
}

// -----------------------------------------------------------------

int getSketchCenterX() {
  return
    myGLWindow.getX() + width / 2;
}

int getSketchCenterY() {
  return 
    myGLWindow.getY() + height / 2;
}

static final com.jogamp.newt.opengl.GLWindow getFrame(final PSurface surface) {
  // used only once ! 
  return 
    (com.jogamp.newt.opengl.GLWindow) surface.getNative();
}

float mouseChangeX() {
  return 
    getSketchCenterX() - (float) MouseInfo.getPointerInfo().getLocation().getX();
}

float mouseChangeY() {
  return
    getSketchCenterY() - (float) MouseInfo.getPointerInfo().getLocation().getY();
}

void updateRotation() {
  cameraRotateX -= mouseChangeX() * cameraSpeed;
  cameraRotateY += mouseChangeY() * cameraSpeed;
  cameraRotateY = constrain(cameraRotateY, -HALF_PI, 0);
}

PVector getMovementDir() {
  return 
    pressedDir.copy().normalize();
}

// --------------------------------------------------------------------------

void mouseClicked() {
  //only used so I can keep track of coordinates in case I need to change things
  player.printPos(); 
  println("X" + mouseX);
  println("Y" + mouseY);
}

void keyPressed() {
  switch(key) {

  case ' ':
    player.startJump(); 
    break; 

  case 'w':
    wPressed = true;
    pressedDir.y = -1;
    break;

  case 'a':
    aPressed = true;
    pressedDir.x = -1;
    break;

  case 's':
    sPressed = true;
    pressedDir.y = 1;
    break;

  case 'd':
    dPressed = true;
    pressedDir.x = 1;
    break;
  }
}

void keyReleased() {
  switch(key) {

  case 'w':
    wPressed = false;
    pressedDir.y = sPressed ? 1 : 0;
    break;

  case 'a':
    aPressed = false;
    pressedDir.x = dPressed ? 1 : 0;
    break;

  case 's':
    sPressed = false;
    pressedDir.y = wPressed ? -1 : 0;
    break;

  case 'd':
    dPressed = false;
    pressedDir.x = aPressed ? -1 : 0;
    break;
  }
}

//==================================================================

class Player {

  PVector bpos = new PVector();
  float bsize  = 100;

  // jump 
  float playermoveY = 0; 
  boolean jump=false; 
  int jumpcounter=0;

  PVector pos, speed;
  float accelMag;
  //float gravity=0.3;

  // constr 
  Player() {
    bpos.y = height/2+bsize/2;

    pos = new PVector();
    speed = new PVector();
    accelMag = 2;
  } // constr 

  void display() {
    pushMatrix();

    translate(bpos.x, 
      bpos.y, 
      bpos.z);
    stroke(255);
    fill(0);
    rotateY(atan2(speed.x, speed.y));
    box(bsize);

    // head 
    float diameter = 60; 
    fill(211, 1, 1); // RED 
    noStroke(); 
    translate(0, -diameter, 33);
    sphere(diameter/2);

    popMatrix();
  }

  void move() {
    PVector accel = getMovementDir().rotate(cameraRotateX).mult(accelMag);

    speed.add(accel);
    pos.add(speed);
    speed.mult(0.9);
  }

  void startJump() {
    jumpcounter=0;
    playermoveY=-21;
    jump=true;
  }

  void jumpManagement() {

    if (jump) {
      bpos.y += 
        playermoveY;
    }

    // stop the jump
    if (bpos.y>=height/2-bsize/2) { 
      bpos.y=height/2-bsize/2;
      if (jumpcounter==0) {
        // bounce
        playermoveY=-9;
        jumpcounter++;
      } else {
        // stop jump
        jump=false;
        playermoveY=0;
      }
    } //if
    else {
      playermoveY++;
    }
  }//func 

  void printPos() {
    println("bpos.x" + bpos.x);
    println("bpos.y" + bpos.y);
    println("bpos.z" + bpos.z);
  }
  //
}
//
2 Likes

Cheers!
Been having troubles with the jump function for a while. I got it to jump, but never bounce. This is a tremendous help. :smiley:

It seems that the player slightly floats above the grid. If this is intended, then disregard the rest of this comment. If not, it’s an easy fix by removing +player.bsize/2 from gridLevelY = height/2+player.bsize/2; in setup() :smiley:

1 Like

thanks, I was confused by that

@Chrisir
I also noticed that one was able to jump, well, infinitely. This is fixed by replacing whatever is inside void startJump() { (I can’t remember) with
if (bpos.y == height/2-bsize/2) { jump=true; jumpcounter=0; playermoveY=-21; }

Then the player should only be able to jump when standing on ground. :slight_smile:

1 Like

While the mouse is hover your window, click and hold the mouse button. As long as you hold it down, your mouse position will update even when outside of your window.