I am developing a first person shooter in Java and I want to implement controls in which movement of the mouse rotates the player. However in Java, I can only get mouse coordinates by using MouseListener events, so the coordinates will stop changing once the mouse cursor leaves the monitor edge and I will be unable to turn the player's view.
Any tips/suggestions on how to do that? Thanks.
I tried using a java.awt.Robot as AerandiR suggests, but there were a couple of problems I ran into, and it's possible other people will run into them as well, so I will elaborate.
If your goal is to keep the cursor in one position (preferably the center of the screen), then you will want to call something like robot.mouseMove(width/2, height/2); at the end of your mouseMoved() method. With this implementation, every time the mouse is moved off center, the Robot will move it back to the center.
However, when the Robot re-centers the mouse, the player will turn back to where it was. In effect, the player will stutter between the original position and a turned position.
To fix this, instead of defining how far your player turns on the difference between where the mouse is now and where it was, define it as the distance from the center.
Like so: turnAmountX += e.getX() - width/2;
Now, if the Robot re-centers the mouse, e.getX() - width/2 will always yield zero.
Recap:
void mouseMoved(MouseEvent e) {
turnAmountX += e.getX() - width/2;
turnAmountY += e.getY() - height/2;
robot.mouseMove(this.getLocationOnScreen().x + width/2,
this.getLocationOnScreen().y + height/2;
}
In some games, on every mouse movement event the cursor is moved back to the middle of the screen, and the view moves with the corresponding magnitude and direction of the mouse event. You can get that vector by calculating the offset of the cursor position to the center of the screen prior to centering the cursor. To move the cursor back to the center of the screen you can try using the java.awt.Robot class.
Since you're building a first person shooter, you'll probably want to hide the center locked cursor, and draw your own crosshair where the player is intending to aim. That will also involve keeping track of where the cursor should be based on the running total of previous mouse movement events.
If you want to achieve behaviour where the view will continue moving relative to the starting position of the mouse (even once the mouse has stopped moving), you could keep a moving sum of all the previous mouse movement vectors, and move the view correspondingly once every frame. However, this probably applies more to something like a flight simulator than a first person shooter.
Related
what I would like to achieve is having the cursor of my game stay in the the "gameplay" area of my window, so the user cannot move the cursor out of those bounds. I DO NOT want the cursor to stay in ONE position, I still want the user to be able to move his mouse around and click, I just want the mouse to be "encaged" in an area. Please see this demonstration:
Game screenshot for demonstration
I want the cursor to stay in the green box just outside the pink markers I made.
So I heard that there was a way to achieve this by using the "Robot" in java or by setting the MouseGrabbed to true, but without finding adequate tutorials, all tests have failed.
I am quite new to Slick2D and java game development in general, so please be very specific and guide me through your ideas.
Thanks in advance!
If I'm understanding you correctly you want the following:
Have a cursor that is limited to the lower green box in your screenshot
Still allow the native cursor to be usable(ungrabbed) when navigating outside of the game window (i.e users can click the x button and such)
I've achieved this before by rendering my own cursor and hiding the native one while in the game window. There's a few steps to accomplishing this. I should mention that this was done with a slightly older version than the current LWJGL offerings, and I'm not sure which version you are running.
Step 1: Disabling the native cursor
You want to disable the native cursor when inside your game window. Grabbing was too aggressive in my case since it disabled the mouse for a windowed game entirely. When initializing your game, try the following:
try {
final Cursor emptyCursor = new Cursor(1, 1, 0, 0, 1, BufferUtils.createIntBuffer(1), null);
Mouse.setNativeCursor(emptyCursor);
} catch (final LWJGLException e) {
//TODO: Consider better exception handling
e.printStackTrace();
}
What this does is render the native mouse as nothing while in your game window. This means the arrow you normally see will disappear when you mouse over your game. This does NOT mean that the mouse is not functional, we have just hidden it.
Step 2: Track mouse movement when gathering keyboard/mouse input
public void collectInput() {
while(Mouse.next()){
this.mouseX = Mouse.getX();
final int newMousePosition = Mouse.getY();
//Only move the cursor on the Y axis if it is between the upper and lower bounds
if(newMousePosition < this.upperBound && newMousePosition > this.lowerBound){
this.mouseY = newMousePosition;
}
this.mouseY = Display.getHeight()- Mouse.getY();
//TODO: Consider adding logging here
}
}
I had a collectInput() method that would grab keypresses/mouse events I thought were necessary. All I'm doing here is grabbing the current X/Y of the mouse in my game window. The Y coordinate is subtracted from the total display height to deal with render coordinates vs mouse coordinates later on. In my case I just used the bounds of my entire window, but you may want to consider not updating X/Y coordinates if they go outside of your green box.
EDIT
Based on your comment, I updated the code block here to not update the Y coordinate if the new coordinate is not within some boundaries. You will want to determine what your x and y boundaries are, and only update your mouse X/Y coordinates if the new coordinates gathered from the Mouse class lie within them.
Step 3: Render your own cursor
Finally, you will want to render your cursor. This looks like any other render you would do with LWJGL. My example assumes you have a texture for this:
//Render mouse texture
Color.white.bind();
this.mouseTexture.bind();
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(this.mouseX, this.mouseY);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(this.mouseX + this.cursorHeight, this.mouseY);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(this.mouseX + this.cursorHeight, this.mouseY + this.cursorWidth);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(this.mouseX, this.mouseY + this.cursorWidth);
GL11.glEnd();
GL11.glDisable(GL11.GL_TEXTURE_2D);
What this results in is that when I am using the mouse in the game window, my custom cursor is rendered. It's hard to tell from the image, but the white circle is now my cursor, and it moves wherever I move the mouse. It's important to note here that the regular native cursor is not being shown due to step 1:
But when I leave the game window, the native mouse is shown, and my custom cursor is left in the last place it received input:
I am developing one simple game in which i have encountered one small but important issue.
I have implemented absolute rotation in my logic.
When i start rotating an object when the object does not have any rotation , it works fine and i can rotate as in any direction without any problem as shown in the following link.
Initial Rotation Video
Now the problem arise when the object does have some rotation , and why i try to rotate in one of the direction , instead of being rotated in desire direction the rotation always starts from initial rotation as shown in the following link.
Rotation issue when shape has some rotation
I think the video shows everything , still if you have any questions please ask me.
I think the problem is , there should be a relative rotation in the direction of mouse pointer from whatever circle is selected .
Now about My Logic,
in mouse press event i just checked
Mouse Press
Whether the shape is selected on the canvas , if yes
if one of the four circles contains mouse point if yes
then initiateRotation
Mouse Drag
Using Vector Maths
I update the motion according to mouse points ,
calculate rotation angle according to the following method
Math.atan2(rotationVector.getY(), rotationVector.getX());
and apply rotation on this shape.
Rotation Vector i get from this class
Vector Rotation
I called above class startMotion in mouse press and updateMotion in mouse drag event.
What am i missing or doing anything wrong ?
We need to see some code to be able to help you out. It looks like you reset the rotation, whenever you initiateRotation, and then the object quickly rotates in place, according to your mouse position when you drag.
Im building something in JOGL and im looking to make the camera move either through using the keyboard or mouse, it doesnt really matter, so long as the camera can pan around the object and possibly zoom in and out. If using the keyboard/mouse is difficult then I also dont mind using some buttons in the applications, e.g. arrows up, down, left and right and a plus and minus button for the zoom but basically whatevers easiest.
Im building something kind of like Lego but its proving to be quite difficult without being able to move the camera.
To move your "camera" you need to apply a glTranslate3f() transform at the beginning of your rendering function. If your camera's location is to be
cameraPos = <cx, cy, cz>
then you should use
glTranslate3f( -cx, -cy, -cz );
This will offset everything that is drawn by that vector.
In order to use the keyboard to make this happen, you will want to use a KeyListener implementation and define the functions specified by the interface.
public void keyPressed( KeyEvent ke ){ // put something intelligent here... }
public void keyReleased( KeyEvent ke ){}
public void keyTyped( KeyEvent ke ){}
Make sure to register this implementing class as a KeyListener to your GLJPanel (or whatever you're using). Then, inside the keyPressed(...) function, check which key is being pressed and increment the appropriate coordinate of the camera.
If you want to get really fancy and allow the mouse to enable you to look around, you can do a similar thing by creating a MouseMotionListener and registering it. The OpenGL transform that is needed to put this into play can vary based on what type of mouse behavior you are looking for. If you just want something simple that will allow you to look around, you can probably get away with tracking mouse motion in the x and y directions and allowing it to modify some offset angles. Moving the mouse in the x direction rotates about the y-axis. Movement in the y direction rotates about the x-axis. As an OpenGL call, as with the glTranslate3f(), you can use glRotatef() to rotate about each axis.
glRotatef( angleX, 1, 0, 0 ); // to rotate about the x-axis
glRotatef( angleY, 0, 1, 0 ); // to rotate about the y-axis
Again, this is just a quick and easy solution. It won't be beautiful, but it will work. If you want to implement something a bit fancier, you can look into computing an arbitrary axis rotation matrix.
http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/
(one of many resources on this topic)
You use a function called "gluLookAt( position of x , position of y , position of z , x of where the camera looks at, y of where the camera looks at, z of where the camera looks at, 0, 1, 0);"
As for the "0, 1, 0" part, leave them as they are as you are just panning around and zooming in. This just affects the tilt of the camera.
I have a fps "camera", and just recently managed to set up mouse movement to rotate the angle of viewing. The one problem with the camera is that the mouse can leave the window and the angles will not rotate anymore. I know I can use a robot method like mouseMove(), however, I've heard that it makes the camera rotation feel very jerky. Is there any other way to keep the mouse in the window, say like, Minecraft? I'm using Minecraft as an example because my program uses LWJGL too, and I was wondering how Notch does it. Any suggestions?
Mouse.setGrabbed(true) at a start-up moment,
and for every game-loop(frame):
catch mouse movement with Y_Angle += Mouse.getDX()*0.1f,
then rotate your view matrix around Y axis on Y_Angle degrees/radians.
For rotation around X and Z axes use Mouse.getDY() and think on your own how to implement right matrix rotation for those, but this is the main idea.
I have tried to use different methods but to no avail. So I come looking for a fresh point of view.
I want to have a sprite follow the touch coordinates of the user. So if they dragged their finger across the screen the sprite would move or tween towards the touch coordinates but continuously update to 'follow' the users finger. If the user stopped moving their finger, the sprite would eventually come to a stop at the final touch coordinates.
I can get the sprite to move and tween to a single set of coordinates but not continuously update to follow along. This is for an android game. its in java. this is one of the basic functions i need to use so im not too far along. that being said I can accept direction for open gl or for canvas.
Any help or direction would be much appreciated. thank you!
On every frame, do
Pos = (Pos * 0.95) + (LastTouch * 0.05);
Adjust the ratios until it feels right. Just make sure they add up to 1.