Quake-like Mouse Control

I read a post by endolf here http://72.14.207.104/search?q=cache:_JTiqa9OGnUJ:www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi%3Fboard%3Djinput%3Baction%3Ddisplay%3Bnum%3D1083727410+jinput+quake&hl=en&ct=clnk&cd=2&client=safari (sorry for the cached google - but the forums seen to have been down for ages now) that suggested achieving quake like mouse look behaviour in java would be ideally suited to jinput.

Ok - great cos thats what I want :). Trouble is I’m struggling to work out how this is achieved - in fact I’m considering moving from jogl to lwjgl purely because of the mouse control (which is crazy - considering their mouse input is apparently based on jinput, which should work fine with jogl). I’ve trawled the lwjgl source to try and work it out - but its not coming to me - I feel like I’m missing a part of JInput.

The functionality I can’t seem to get is what lwjgl achieves with ‘Mouse.setGrabbed(true)’ - the mouse control is ‘grabbed’ from the underlying OS and the mouse doesn’t scroll out of the window. Easy to see what I’m talking about if you run the lwjgl MouseTest annd try modifying the setGrabbed to false. Maybe its achieved by moving the mouse back to the centre of the screen all the time. Dunno but I figure its more likely that the hardware events are not being passed to the OS.

So how do you do this with JInput? The polling bit I get, so I can control my scene with the mouse - as long as I don’t want to turn more than 270 degrees and lose the mouse off the edge of the window. If anyone could give me any idea on this that would be a great - if I’ve missed pile of docs or how-to’s or a wiki or something, a pointer to that would be much appreciated as well - thanks,

Colin

P.S. Once I’ve got it sorted out I’d be happy to post the walkthrough on a wiki somewhere if there is one…

It soudns liek youa re confusing the mouse and the the cursor.

The mouse is an input device.

The cursor is an output device.

Typically a game will draw its own cursor and clip it to its space.

I dont quite get this. The OS aught to be returning mouse events regardless of where the cursor is in relation to the window.

I know this is the case in Linux. What OS are you under? Its possible the plug-in needs a property to tell it to make some OS specific call on your OS, though this would be a bizzare OS… (which is why Im guessing its Winblows but maybe Im wrong.)

Hi

As I understand it, lwjgl doesn’t use jinput for mouse or keyboard, but does for other controllers. Under XWindows on linux, I also get issues when I move the mouse out of the window using lwjgl, but not using jinput.

HTH

Endolf.

Thanks for the responses…

I get the difference beetween the mouse and the cursor - but it sounds like I might have things a bit confused in other ways. Perhaps I need to roll back and ask some more fundamental questions. Perhaps JInput isn’t what I’m after.

Can I stop the OS (OS X in this case) Windowing System cursor moving while my game window has focus? It seems the answer is yes, because both lwjgl and jake2 achieve this. Did they write their own custom native implementation to achieve this - or is there a method somewhere that I’m missing.

Essentially this would have to happen in one of three ways -

  1. The Windowing System stops polling the mouse driver (if thats how it gets mouse movement data - JInput model)
  2. The Windowing System would have to stop listening for mouse movement events (if thats how it works - the AWT model)
  3. The mouse driver the Windowing System is using would have to present information (polling or eventing) that indicated no mouse movement. If the model is eventing, then this would prrobably mean never raising the event.

The ugly other option here would be to continually move the cursor back to the centre of the screen with something like the java.awt.Robot class.

I can hide the system mouse cursor and draw my own in JOGL, but I suspect that if any of the above 3 things happened, then AWT would not receive mouse events either. Hence I would need something like JInput to receive mouse movement data.

So the question is - for Quake-like mouse control - how do I stop the Windowing System cursor from moving when my window has focus?

At the moment I think I’m going to have to go with JInput and java.awt.Robot - but that seems dodgy - hopefully the Robot won’t interact wiith JInput - seems ok at first glance. Cheers,

Colin

Games almost always hide the system cursor and draw their own as part of their game render loop.

Hide it and draw your own.

Hi Jeff - that works except that even with the cursor hidden it still tracks - and when it goes past the edge of the screen - i.e. my window loses focus - the cursor reappears - I can’t move the mouse infinitely in any direction - only within the bounds of my game window. Basically just because my window hides the cursor, doesn’t mean the OS X windowing system stops tracking it - I need to be able to move the mouse any distance in any direction without the OS X windowing system cursor moving. Cheers,

Colin

If you don’t want to use LWJGL then you already had the answer with the above. Its not particularly pretty but does work pretty cleanly.

LWJGL takes the line that its a game development library so do whatever it wants at the native level to make the tools available to the user - hence they can implement setGrabbed().

JInput takes the line that its a way of getting input from various devices through the native layer. Hence it doesn’t have any interest in cursors, making them visible or constraining them to the screen. (which are of course output - to the screen :)).

You have the answer from yourself :slight_smile: - just run with it.

Kev

HMm. I guess that gets into the question of how Apple intrepted cursor hidefor their JRE . Clearly they felt it was important to make it still possible to swtich focus when i nwindowed mode. Honestly I cant entirely disagree with them. If you are running windowed then, at least from a systems POV, you are telling the system yo uwant access to multiple apps at once. If it let the windowed app entirely take the cursor away then it coudl repevent acess to other apps, which breaks the window metaphor.

Is there a reason why you really want to run windowed but have what soudns like full-screen type fucntionality? If not Id go full screen. if so, well then yes the robot hack OR writing your own JNi to hit the OS directly might be the only solutions.

Thanks - in the end I chose to port my app. to lwjgl - which means the raft of refactorings I’ve had in the back of my mind for a while can be implemented :slight_smile: - you’re right though - it does feel weird to have the mouse ‘grabbed’ in a window, but isn’t to bad once you geet used to it - ‘apple-tab’ app switching is ok enough. Thanks for the input - cheers,

Colin

I tried using java.awt.Robot to warp the cursor. It worked, but very slowly: it could take upwards of a hundred milliseconds to read the mouse position once on Mac OS X. Windows performed significantly better, but was still sluggish. I also tried outsourcing the cursor warping to a native C method, but that increased the lag to more than one second for some reason.

I finally wound up using the approach mentioned in this forum of freezing the cursor and reading the mouse deltas.

For freezing the cursor, use the following Carbon function (if you’re on Mac OS X):
CGAssociateMouseAndMouseCursorPosition(false);

Reading the mouse deltas is a little bit more obnoxious, just because JNI can be very tempermental.

CGMouseDelta x, y;
CGGetLastMouseDelta(&x,&y);

Then x and y represent the amount by which the mouse position changed the last time the application received a mouse event. By application, I mean the parent process that contains the JVM. Whenever you launch a Java application on Mac OS X it seems like the JVM gets wrapped up inside a Cocoa application. So I cannot guarantee that my techniques would work in an applet.

Now, of course my native library only works on OS X. But I think that this behavior would not be too hard to port to other platforms. It’s obviously been done before.

If you still have any interest in using JOGL, I would be happy to post my Java and C source files, as well as my shared libraries and JARs.

Why bother reading the XY delta with JNI?

You can do that fine from JInput and then thats that much more thats cross paltform.

As for robot, I think you missed the point.

You dont read with Robot. You read with JInput

You just reset the cursor every frame to the center of your window with Robot. And if you do that, you need NO JNI at all.

How well does Jake2 work on your machine? I’m pretty sure they use java.awt.Robot to implement the cursor warping and it seems to work pretty well (and portably, with no additional native code needed).

I’d personally be interested in seeing your solution but would like to know first whether the sluggish performance you saw is reproducible with e.g. Jake2. Do you have a test case for the sluggish behavior? Maybe it should be reported to Apple.

Ken,

I think the trick here is that he misunderstood,

I believe was using Robot to read the cursor.

And that was what was slow.

I know that the mouse reading functionality is available in JInput. It’s just that learning how to use somebody else’s JARs always takes time and I sometimes get lazy. That’s why I wrote JNI calls. Besides, JInput is using JNI itself.

Jake2 runs at an acceptable rate on my machine, except if you try to use the mouse.

Sure, just like JOGL has to use JNI.

The question is, would you rather keep your own JNI up to date, fully functional, and port it yourself to every new platform you want to go or do you want to leverage what the community is already doing for you.

Your little peice of JNi isnt much, but ist also not nearly as functional as JInput. And to reach Jinput’s functionality in terms of dynamic controlelr discovery and usage as well as portability, you would have to do some major re-inveting the wheel across multiple platforms.

I’d much rather let someone else handle the headache of writing JNI code.

Here’s the thing: this mouse input issue is the one thing that might discourage me from using Java for my game.

So JInput is wonderful. It does everything I need as far as user input goes except that it doesn’t allow you to unplug the cursor from the mouse.

I’ve tried LWJGL for this, and it works great, but I dislike their OpenGL bindings. It is particularly obnoxious that gluUnProject wants double-scripted projection arrays (where OpenGL uses single-scripted arrays as a rule) whereas glGetDouble gives you a DoubleBuffer. So if I went with LWJGL, I’d need a way to use JOGL in place of LWJGL’s own GL.

I’ve had good experiences with Simple DirectMedia Layer in C, and I know that there is a project to bind SDL to Java (http://sdljava.sourceforge.net/). Unfortunatley, sdljava is incomplete and still missing most of OpenGL.

And I’m not satisfied with my little native library.

So what’s a poor Java programmer like me supposed to do?

In my opinion we should fix JInput to do what you want. I am definitely in favor of restructuring the internals and adding new functionality where necessary. @endolf, @elias, what is the status of the OS X work that you mentioned above?

You can use JOGL’s OpenGL bindings with LWJGL (and vice versa). To use JOGL with LWJGL’s OpenGL context, call GLDrawableFactory.createExternalGLContext() when LWJGL’s OpenGL context is current, and call GLContext.getGL() on the resulting GLContext object when you want to draw. LWJGL has similar functionality.

[quote]You can use JOGL’s OpenGL bindings with LWJGL (and vice versa). To use JOGL with LWJGL’s OpenGL context, call GLDrawableFactory.createExternalGLContext() when LWJGL’s OpenGL context is current, and call GLContext.getGL() on the resulting GLContext object when you want to draw. LWJGL has similar functionality.
[/quote]
Thank you. I’ll try that.

Here’s another question: for the time being, if I used my own native library to surpress cursor movement, would JInput still report mouse motion?

Correct. Thats because that is an output system issue not an input system issue.

I would MUCH rather see that functionality developed in a more approiate API (really IMHo it really should be part of AWT as it is an artifact of the windowing system, not the underlying hardware, Maybe make it a JOGL call??)

Having said that, if we really can find noone else to pick that up, I suppose we could pollute JInput’s API with it. But I rreally DO believe it woudl be a necessity driven pollution.