Getting Android Input to Work

I’ve started playing with JME3 on a Motorola Droid (the first one). I’m running Android 2.2 and it supports OpenGL 2. I’ve got the first few tutorials to work (create a box, make it spin, etc). However, I’ve haven’t been able to figure out how to get the keyboard key events to work.



When the game starts, I hit both the DPAD Center key as well as the Enter key, but nothing seems to happen. Is there something I need to do to map the Android keyboard keys into the addMapping?



The touch screen seems to be working because when I use the touch screen, the scene rotates around.



The code for the key events I’m using is the following:



/** Custom Keybinding: Map named actions to inputs. /

/
* Called from simpleInitApp /

private void initKeys() {



int key = KeyInput.KEY_RETURN;



// You can map one or several inputs to one named action

inputManager.addMapping(“Center”, new KeyTrigger(key));

inputManager.addMapping(“Center2”, new KeyTrigger(key));



// Add the names to the action listener.

inputManager.addListener(actionListener, new String[]{“Center”});

inputManager.addListener(analogListener, new String[]{“Center2”});



}



private ActionListener actionListener = new ActionListener() {

public void onAction(String name, boolean keyPressed, float tpf) {

if (name.equals(“Center”) && !keyPressed) {

Vector3f v = player.getLocalTranslation();

player.setLocalTranslation(v.x + 1, v.y, v.z);

Log.d(“GAME”, “Center key action”);

}

}

};



private AnalogListener analogListener = new AnalogListener() {

public void onAnalog(String name, float value, float tpf) {

if (name.equals(“Center2”)) {

Vector3f v = player.getLocalTranslation();

player.setLocalTranslation(v.x - value
speed, v.y, v.z);

}

}

};

Analog events are not generated, only Mouse is simulated - no joysticks.



You have to listen for TouchEvents, inside there are the keycodes, too:



[java]

// Register ourselves as a touch listener

inputManager.addMapping("Touch", new TouchTrigger(0));

inputManager.addListener(this, new String[]{"Touch"});



/**

  • Gets called by the InputManager on all touch/drag/scale events

    */

    @Override

    public void onTouch(String name, TouchEvent evt, float tpf)

    {

    switch(evt.getType())

    {

    case MOVE:

    lastX = evt.getX();

    lastY = evt.getY();



    pressure = evt.getPressure();

    break;



    case TAP:

    lastX = evt.getX();

    lastY = evt.getY();

    break;



    case KEY_DOWN:

    keycode = evt.getKeyCode();

    break;



    default:

    logger.info("Event Type " + evt.getType());

    break;

    }



    evt.setConsumed();

    }

    [/java]
3 Likes

Understood. Working fine. Thanks.

A basic interface for touchscreen phones.



The camera is moved with the translation to mouse moves.

Longpressed is mapped moves forward until Up stops the movement.



The next coding will be to create buttons on a HUD for navigation



[java]

package sg.edu.sp.dmit.ANBDemo;

import android.util.Log;



import com.jme3.app.SimpleApplication;

import com.jme3.asset.AssetManager;

import com.jme3.asset.TextureKey;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.PhysicsSpace;

import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;

import com.jme3.bullet.control.CharacterControl;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.bullet.joints.ConeJoint;

import com.jme3.bullet.joints.PhysicsJoint;

import com.jme3.input.android.AndroidInput;

import com.jme3.input.android.AndroidTouchInputListener;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.input.controls.TouchListener;

import com.jme3.input.controls.TouchTrigger;

import com.jme3.input.event.TouchEvent;

import com.jme3.light.AmbientLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Cylinder;



import com.jme3.shadow.BasicShadowRenderer;

import com.jme3.texture.Texture;

import com.jme3.texture.Texture.WrapMode;



public class Test14 extends SimpleApplication implements ActionListener,TouchListener {



private BulletAppState bulletAppState = new BulletAppState();

BasicShadowRenderer bsr;

Material mat;

Material mat2;

Material mat3;

private boolean left = false, right = false, up = false, down = false;

private Vector3f walkDirection = new Vector3f();

private CharacterControl player;



public void simpleInitApp() {

bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);



inputManager.addMapping("Touch", new TouchTrigger(0));



inputManager.addListener(this, new String[]{"Touch"});





initMaterial();

createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());



CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);

player = new CharacterControl(capsuleShape, 0.05f);

player.setJumpSpeed(20);

player.setFallSpeed(30);

player.setGravity(30);

player.setPhysicsLocation(new Vector3f(0, 10, 0));



bulletAppState.getPhysicsSpace().add(player);

}



public static void createPhysicsTestWorld(Node rootNode, AssetManager assetManager, PhysicsSpace space) {

AmbientLight light = new AmbientLight();

light.setColor(ColorRGBA.LightGray);

rootNode.addLight(light);



Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

material.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));



Box floorBox = new Box(140, 0.25f, 140);

Geometry floorGeometry = new Geometry("Floor", floorBox);

floorGeometry.setMaterial(material);

floorGeometry.setLocalTranslation(0, -5, 0);

// Plane plane = new Plane();

// plane.setOriginNormal(new Vector3f(0, 0.25f, 0), Vector3f.UNIT_Y);

// floorGeometry.addControl(new RigidBodyControl(new PlaneCollisionShape(plane), 0));

floorGeometry.addControl(new RigidBodyControl(0));

rootNode.attachChild(floorGeometry);

space.add(floorGeometry);



//movable boxes

for (int i = 0; i < 12; i++) {

Box box = new Box(0.25f, 0.25f, 0.25f);

Geometry boxGeometry = new Geometry("Box", box);

boxGeometry.setMaterial(material);

boxGeometry.setLocalTranslation(i, 5, -3);

//RigidBodyControl automatically uses box collision shapes when attached to single geometry with box mesh

boxGeometry.addControl(new RigidBodyControl(2));

rootNode.attachChild(boxGeometry);

space.add(boxGeometry);

}



}



public void initMaterial() {

mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");

key.setGenerateMips(true);

Texture tex = assetManager.loadTexture(key);

tex.setWrap(WrapMode.Repeat);

mat.setTexture("ColorMap", tex);



mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");

key2.setGenerateMips(true);

Texture tex2 = assetManager.loadTexture(key2);

mat2.setTexture("ColorMap", tex2);



mat3 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg");

key3.setGenerateMips(true);

Texture tex3 = assetManager.loadTexture(key3);

tex3.setWrap(WrapMode.Repeat);

mat3.setTexture("ColorMap", tex3);

}



@Override

public void onAction(String binding, boolean value, float tpf) {



Log.e("",""+binding);

}



@Override

public void onTouch(String binding, TouchEvent evt, float tpf) {

float x;

float y;

float pressure;

switch(evt.getType())

{

case MOVE:

x = evt.getX();

y = evt.getY();



pressure = evt.getPressure();

break;



case TAP:

x = evt.getX();

y = evt.getY();

break;



case LONGPRESSED:

// move forward

up = true;

break;



case UP:

up = false;

break;



case FLING:

break;



default:



break;

}

Log.e("","Event Type " + evt.getType());

evt.setConsumed();





}



@Override

public void simpleUpdate(float tpf) {



Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);

Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);



walkDirection.set(0, 0, 0);

if (left) { walkDirection.addLocal(camLeft); }

if (right) { walkDirection.addLocal(camLeft.negate()); }

if (up) { walkDirection.addLocal(camDir); }

if (down) { walkDirection.addLocal(camDir.negate()); }

player.setWalkDirection(walkDirection);

cam.setLocation(player.getPhysicsLocation());

}

}

[/java]

2 Likes

@larynx - Have you any work around the acceleramotor through to the input manager?

@mikegriffin, looks great! I’m definitely going to try this with the Android/jME3/Camera integration I’ve been working on as its a touchscreen only phone

After attempting to get niftygui running android I have created a simple HUD.



I am unfamiliar with nifty but it looks good and when this is running on android I will probably use that… in the meantime …



[java]

package sg.edu.sp.dmit.ANBDemo;



import android.util.Log;



import com.jme3.animation.AnimChannel;

import com.jme3.animation.AnimControl;

import com.jme3.animation.AnimEventListener;

import com.jme3.animation.LoopMode;

import com.jme3.app.SimpleApplication;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

import com.jme3.input.MouseInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.input.controls.TouchListener;

import com.jme3.input.controls.TouchTrigger;

import com.jme3.input.event.TouchEvent;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Ray;

import com.jme3.math.Vector2f;

import com.jme3.math.Vector3f;

import com.jme3.renderer.Renderer;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Quad;

import com.jme3.scene.shape.Sphere;

import com.jme3.ui.Picture;



public class Test17 extends SimpleApplication implements TouchListener,AnimEventListener {



private AnimChannel channel;

private AnimControl control;

Node player;



@Override

public void simpleInitApp() {



initKeys(); // load custom key mappings



settings.setHeight(480);

settings.setWidth(800);



// create my picture buttons

Picture pic = new Picture("HUD Picture");

pic.setImage(assetManager, "Textures/ColoredTex/Monkey.png", true);

pic.setWidth(80f);

pic.setHeight(80f);

pic.setPosition(0f, 0f);

guiNode.attachChild(pic);



Picture pic2 = new Picture("HUD Picture");

pic2.setImage(assetManager, "Textures/ColorRamp/cloudy.png", true);

pic2.setWidth(80f);

pic2.setHeight(80f);

pic2.setPosition(85f, 0f);

guiNode.attachChild(pic2);



Picture pic3 = new Picture("HUD Picture");

pic3.setImage(assetManager, "Textures/ColorRamp/toon.png", true);

pic3.setWidth(80f);

pic3.setHeight(80f);

pic3.setPosition(170f, 0f);

guiNode.attachChild(pic3);



DirectionalLight dl = new DirectionalLight();

dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());

rootNode.addLight(dl);



player = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");

player.setLocalScale(0.5f);

rootNode.attachChild(player);



control = player.getControl(AnimControl.class);

control.addListener(this);

channel = control.createChannel();

channel.setAnim("stand");



}



/** Declaring the "Shoot" action and mapping to its triggers. */

private void initKeys() {



inputManager.addMapping("Touch", new TouchTrigger(0));

inputManager.addListener(this, new String[]{"Touch"});

}



public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {

if (animName.equals("Walk")) {

channel.setAnim("stand", 0.50f);

channel.setLoopMode(LoopMode.DontLoop);

channel.setSpeed(1f);

}

if (animName.equals("pull")) {

channel.setAnim("stand", 0.50f);

channel.setLoopMode(LoopMode.DontLoop);

channel.setSpeed(1f);

}

if (animName.equals("Dodge")) {

channel.setAnim("stand", 0.50f);

channel.setLoopMode(LoopMode.DontLoop);

channel.setSpeed(1f);

}

}



@Override

public void onTouch(String binding, TouchEvent evt, float tpf) {

float x;

float y;

x = evt.getX();

y = evt.getY();

switch(evt.getType())

{

case MOVE:



break;



case TAP:



break;



case DOWN:



if (x>0&&x<80&&y>0&&y<80){

Log.e("","You touched " + x + " " + y + " which is button 1!");



if (!channel.getAnimationName().equals("Walk")) {

channel.setAnim("Dodge", 0.50f);

channel.setLoopMode(LoopMode.Loop);

}

}

if (x>85&&x<165&&y>0&&y<80){

Log.e("","You touched " + x + " " + y + " which is button 2!");

if (!channel.getAnimationName().equals("Walk")) {

channel.setAnim("pull", 0.50f);

channel.setLoopMode(LoopMode.Loop);

}

}

if (x>170&&x<250&&y>0&&y<80){

Log.e("","You touched " + x + " " + y + " which is button 3!");





if (!channel.getAnimationName().equals("Walk")) {

channel.setAnim("Walk", 0.50f);

channel.setLoopMode(LoopMode.Loop);

}



}





break;



case UP:



break;



case FLING:

break;



default:



break;

}

Log.e("","Event Type " + evt.getType() + " x="+x+" y="+y);

evt.setConsumed();





}



@Override

public void onAnimChange(AnimControl arg0, AnimChannel arg1, String arg2) {

// TODO Auto-generated method stub



}

}

[/java]

2 Likes

I have started another thread for the accelerometer

http://hub.jmonkeyengine.org/groups/android/forum/topic/using-the-accelerometer/?#post-146098

@mikegriffin nifty doesn’t work on android? :frowning:

Huh? Yeah it does.

1 Like

ah right cool :), well mikegriffin seems to know a lot about android, and said less than a week ago:

After attempting to get niftygui running android I have created a simple HUD.
I am unfamiliar with nifty but it looks good and when this is running on android I will probably use that… in the meantime …..

so i wasn't sure

The nifty version that came with alpha-4 still had some AWT dependencies and didn’t run on android, the current nightly does.

awesome :slight_smile:

Where are the latest nightly builds?



http://jmonkeyengine.com/nightly/ seems to end 29 August?

in jmp go to, tools > plugins > settings > update to nightly

I don’t understand



I updated the jmp which updated a load of stuff for jmp but the new jMonkeyEngine3.jar files aren’t available.



I refer to this document

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:setting_up_netbeans_and_jme3?s[]=nightly&s[]=builds

Yes they are, the library entries “jme3” and “jme3-libraries” etc.have been updated, the default project uses them and hence now uses the updated jars if you didn’t change the project settings. Just make sure you use the library entries instead of trying to reference jars directly.

Btw, you update via Tools->Settings… Just read the manual on updating (press F1 and select “Updating the SDK” in the TOC).

Ok.



I have had a poke around and found some updated jars here in

AppDataRoaming.jmonkeyplatformdevlibs

within my c:Users folder - I am assuming that this is where they get updated through the update process - I can then fish them out from here and use them in … Eclipse. :slight_smile:



I see there is a jMonkeyEngine3-android.jar file in there which I am also assuming is the one to use.

… why you read the netbeans setup page when you use eclipse?? theres a page that details the setup in eclipse too… whatever. I suggest just building it yourself from svn, even eclipse can build ant projects.

All I want is a “stable” jmonkey engine jar which is what the nightly build folder used to provide.



If I use the svn - I have to spend time compiling the core engine, working out why it didn’t build and never getting anything deployed in runtime to my android phone.