Input handler for strategy games

I've made an input handler for strategy games, hope someone will find it useful.



Features:

  • spherical look with configurable limits (e.g. 10 to 90 degrees vertical axis and 0 to 180 degrees horizontal axis)
  • automatically adjusts the scrolling direction based on the camera orientation
  • input filters for scrolling, looking and zooming (pretty much everything)
  • fully configurable (including any custom coordinate system, eg: x and y as 2d location and z as height)
  • can seamlessly switch between software and hardware mouse
  • mouse pointer animation
  • cursor management
  • integrated follow object mode (a chase-cam that is more suitable for a strategy game)
  • demo with a full theme of animated cursors and most of usage examples
  • complete input filter framework that can be easily used in other handlers
  • spatial controller to smoothly move a spatial from point a to point b using a spring filter, while the destination (point b) is changing dynamically.
  • optional camera effects: one for smoothly taking over camera into strategicHandler mode and another for smoothly flying a camera to a desired location.



    Controls:

    Scroll the window by moving mouse to the edge of the screen or by using arrows on the keyboard.

    Hold the right mouse button or LEFT_CONTROL to rotate the view with the mouse or use HOME <-> END, DEL <-> PAGE_DOWN.

    Use mouse wheel or INSERT <-> PAGE_UP to zoom.

    Press KEYPAD_ENTER to toggle between hardware and software mouse.



    Hardware vs Software mouse:

    If you are using the hardware mouse in windowed mode, your mouse will be able to leave window,

    so you can have the game running and browse web for example.

    Using the software mouse will lock the pointer inside the window so that it becomes possible to scroll

    the screen by moving the mouse to the edge of the window.



    Edit: hosting changed to http://code.google.com/p/jmeaddons/

Wow this is really great, I've been wanting to make a stategy game for a while and this takes some of the hard work out of it (I originaly started using soya3d a python 3d engine but after finding out about jmonkey it's out the door) I still have to learn more about java and jme but this has gotten me off to a running start.  Thanks a lot.

I've been trying to use this with some random terrain and I'm not sure how to make the camera not go through the terrain, any ideas?

I'll get on it right away, but if you cant wait, here are is how to make a quick fix:



What you need are two height values: one for camera and another one for the point the camera is looking at. You will have to change the StrategicHandler.update() method as follows:



// pseudo-code:

camera.setLocation(converter.getCameraLocation() + cameraOffsetVector);

camera.lookAt(converter.getObservedLocation() + observedPointOffsetVector, converter.getWorldUp());



So the update method has to query the terrainPage for those two hight values. Alternatively you can inject those two values before calling the update method. Either way, some modification to the update method and update sequence are needed. Yet another way is make all the transformations to the camera in game's update method, instead of controller's update method…


Ok, Ive got it working…


  1. change StrategicHandler class as follows:



    public void update(float time) {

    super.update(time);



    handleMouse(time);



    converter.processInputs(time);

    }



    public Vector3f getCamerLocation() {

    return converter.getCameraLocation();

    }



    public Vector3f getObservedPoint() {

    return converter.getObservedLocation();

    }


  2. Assuming that you are using TerrainPage instance named "terrain", add the following code to your game's update method:

    // eg: public void myUpdateMethod() {



    StrategicHandler sh = (StrategicHandler) input;



    Vector3f observedPoint = sh.getObservedPoint();

    Vector3f camLocation = sh.getCamerLocation();



    float pointHeight = terrain.getHeight(observedPoint);

    float camTerrainHeight = terrain.getHeight(camLocation);

    float camPointHeight = pointHeight + camLocation.y;

    float finalPointHeight;

    float finalCamHeight;



    if (camPointHeight > camTerrainHeight) {

    finalPointHeight = pointHeight;

    finalCamHeight = camPointHeight;

    } else {

    finalPointHeight = camTerrainHeight - camLocation.y;

    finalCamHeight = camTerrainHeight;

    }



    Vector3f pointOffset = new Vector3f(0, finalPointHeight, 0);

    Vector3f finalObservedPoint = pointOffset.addLocal(observedPoint);



    Vector3f camOffset = new Vector3f(0, finalCamHeight, 0);

    Vector3f finalCamLocation = camOffset.addLocal(camLocation);



    cam.setLocation(finalCamLocation);

    cam.lookAt(finalObservedPoint, Vector3f.UNIT_Y);

    //}



    That is a bit verbose, but hopefully more clear… Also you might want to rewrite this code to avoid creating new Vector3f instances.

    Let me know if it helps.

thanks for your help, it worked really well.  I'm going to tinker around with it some more.  Once again thanks.

No problem! I need all the input and testing I can get.

Expect another release in a week or so.  :wink:

I've added some more features to strategicHandler, as well as done some overall polish…



new:

  • demo with terrain
  • code to adjust camera height based on terrain
  • mouse input filter while rotating view with the mouse
  • input filters for keyboard rotation and zoom
  • all the configuration code is there, everything is now fully configurable



    improvements:
  • overall code improvements
  • a very good set of defaults



    The source code and binaries are now in two separate archives. Also the binaries are compiled for Java 5 (last version was compiled for Java 6 and I realize some people might not have it… my bad). I have also included a readme file.



    Edit: hosting changed to http://code.google.com/p/jmeaddons/

cool I'll check it out when I have a chance

Hi I keep getting:

Caused by: java.lang.Error: Unresolved compilation problem:

MouseButtonBinding.RIGHT_BUTTON cannot be resolved

I'm using jdk 6 and the latest jme from cvs, if it means anything I'm on linux using eclipse.

This is very strange, because i also use jdk6 with jme from cvs and eclipse on linux…



The full path to that button is

com.jme.input.controls.binding.MouseButtonBinding.RIGHT_BUTTON

It's supposed to be in jme. Make sure it's there (maybe it was removed very recently). I've tested the demo with the latest release of jme (jars) and it was working.

You can also try to do "Project ->Clean" from the top menu in eclipse. If it the error is still there, just change MouseButtonBinding.RIGHT_BUTTON to 1 in the source code.

my bad, I updated from cvs but didn't rebuild, I've done that and now everything is fine, thanks for your hard work.

Your welcome. Im working to get cursor animation, should be done in a couple of days.

I have update today a jme folder, and I have a error in Demo.java in line 68 which look like this:


LoggingSystem.getLogger().setLevel(java.util.logging.Level.WARNING);



There is info that the method getLogger() is undefined for LoggingSystem :/
Whats wrong?

^^ This has nothing to do with the thread it is in (I know, that's not very unusual around here, but this time there are no amphibians involved :D), so I answered it elsewhere:

http://www.jmonkeyengine.com/jmeforum/index.php?topic=5596.msg44569#msg44569

Well, you beat me to it, hevee :wink:

Just as I was warming up my eclipse to figure out the answer…

New release.


  • Mouse management and cursor animation are now in a separate jar.
  • Demo now includes a full theme of animated cursors.
  • Follow object mode.
  • API changes to be more consistent with jme. Eg: setWorldTranslation() instead of setLocation().



    Edit: hosting changed to http://code.google.com/p/jmeaddons/

I am having a problem with the right button. The mouse gets stucked on clicked position.

The most likely problem is that you are not setting a cursor. You have to set a cursor every frame to clear any remaining states. This is done so you can change cursors based on picking. Otherwise the cursor would have been set twice: once to restore a previous state and once to apply a new state. And there is a somewhat large overhead when setting a harware cursor (you don't want to do it twice if avoidable) and the harware cursor tends to flicker when changed on linux, so changing it twice would have given too much flickering.



Look how its done in demo it has a big comment section saying "Remember to update your cursor every frame."



If that dosent resolve a problem then something very strange is going on… And to fix it, I need to replicate the problem first. So give me as much details as possible when the problem occurs.

  1. How often does it occur? (Always, Sometimes, Rarely).
  2. Do you have to press anything else for that to occur? (Any keys on keyboard, any mouse buttons)?
  3. Are you following the object, object rotation when that occurs?
  4. Are you using hardware mouse or software mouse when that occurs?
  5. Does the same thing happens when using press CTRL key?
  6. What version of jme you are using (release # or from CVS)?
  7. Does it occur in the included demo or in your own code where you are trying to integrate the handler?



    Also you can check if the mouseInput is reporting your button as being pressed using

System.out.println(MouseInput.get().isButtonDown(1));

I was not updating cursor, that