Nub Question


Im just getting started with jme3 and am running through the tutorials. I’m trying to piece them together in an attempt to gain a good foundation but I am stumped on one part. I’ve created a blue floor, a ninja, and self (camera). I can walk on the floor, but the physics don’t seem to be “pulling” the ninja down onto the floor. Any help is appreciated.


package mygame;


import com.jme3.bullet.BulletAppState;

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

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

import com.jme3.bullet.nodes.PhysicsCharacterNode;

import com.jme3.bullet.nodes.PhysicsNode;

import com.jme3.bullet.util.CollisionShapeFactory;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;

public class Main extends SimpleApplication implements ActionListener {

private BulletAppState bulletAppState;

private PhysicsNode landscape;

private PhysicsCharacterNode player, enemy;

Spatial ninja;

private Vector3f walkDirection = new Vector3f();

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

public static void main(String[] args) {

Main app = new Main();




public void simpleInitApp() {

/** Set up Physics */

bulletAppState = new BulletAppState();


//create light

DirectionalLight sun = new DirectionalLight();

sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));

viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f));



//create floor

Box b = new Box(new Vector3f(0,-5,0), 25, .5f, 25);

Geometry floor = new Geometry(“Box”, b);

Material mat = new Material(assetManager, “Common/MatDefs/Misc/SolidColor.j3md”);

mat.setColor(“m_Color”, ColorRGBA.Blue);


MeshCollisionShape sceneShape =


landscape = new PhysicsNode(floor, sceneShape, 0);

//create ninja

ninja = assetManager.loadModel(“Models/Ninja/Ninja.mesh.xml”);

ninja.scale(0.05f, 0.05f, 0.05f);

ninja.rotate(0.0f, -3.0f, 0.0f);

ninja.setLocalTranslation(2.0f, 10.0f, -1.0f);

enemy = new PhysicsCharacterNode(new CapsuleCollisionShape(1.5f, 6f, 1), .05f);




enemy.setLocalTranslation(2.0f, 10.0f, -1.0f);

//create player

player = new PhysicsCharacterNode(new CapsuleCollisionShape(1.5f, 6f, 1), .05f);




player.setLocalTranslation(new Vector3f(5, 10, 5));

//add objects to view





//add physic objects





private void setupKeys() {

inputManager.addMapping(“Lefts”, new KeyTrigger(KeyInput.KEY_A));

inputManager.addMapping(“Rights”, new KeyTrigger(KeyInput.KEY_D));

inputManager.addMapping(“Ups”, new KeyTrigger(KeyInput.KEY_W));

inputManager.addMapping(“Downs”, new KeyTrigger(KeyInput.KEY_S));

inputManager.addMapping(“Jumps”, new KeyTrigger(KeyInput.KEY_SPACE));

inputManager.addListener(this, “Lefts”);

inputManager.addListener(this, “Rights”);

inputManager.addListener(this, “Ups”);

inputManager.addListener(this, “Downs”);

inputManager.addListener(this, “Jumps”);


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

if (binding.equals(“Lefts”)) {

if (value) { left = true; } else { left = false; }

} else if (binding.equals(“Rights”)) {

if (value) { right = true; } else { right = false; }

} else if (binding.equals(“Ups”)) {

if (value) { up = true; } else { up = false; }

} else if (binding.equals(“Downs”)) {

if (value) { down = true; } else { down = false; }

} else if (binding.equals(“Jumps”)) {





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()); }




System.out.println("Ninja: " + ninja.getLocalTranslation());

System.out.println("Enemy: " + enemy.getLocalTranslation());






why do you do that?

I added that in case the collision object was moving but not the ninja (prior to adding my output lines). Even if it is commented out he still just floats mid air.

My thought was we keep moving the camera to the location of the physics player object, so maybe we need to move the ninja to his physics object.

Actually you should attach the ninja to the PhysicsCharacterNode, but also note the recent changes in the physics system, A CharacterControl is what you should use from alpha-4 on.

Found my problem, I was not adding both ninja and enemy to rootNode. This fix made it work.

I replaced

[java]enemy = new PhysicsCharacterNode(new CapsuleCollisionShape(1.5f, 6f, 1), .05f);[/java]


[java]enemy = new PhysicsCharacterNode(ninja, new CapsuleCollisionShape(1.5f, 6f, 1), .05f);[/java]

but I still need [java]ninja.setLocalTranslation(enemy.getLocalTranslation());[/java] to get the ninja to stay with his collision shape.

I assume I shouldnt have to do the ninja.setLocalTranslation(enemy.getLocalTranslation()); but this is the only way i can get it to work?


Okay, so my final problem was I was setting the translation for the ninja at the start. Once I removed that and only translated the enemy, they stayed together.

Thanks so much!

BTW, can you give me more details about CharacterControl? I saw PhysicsCharacterControl in the API but my JME isn’t recognizing it when i try import com.jme3.bullet.control.PhysicsCharacterControl; (or if i remove Physics from the name)

Well you need to update to the latest nightly to use that (see Manual - F1).

Edit: I just ran a build to reflect the recent name changes, should be done in some minutes.