Hello everybody!
I want to program an application where small boxes move inside a 3D-Scene
These boxes should:
- be visible
- there should be gravity and collision detection enabled for them
- it should be possible to move them continously (not by keyboard or mouseinput - I want that they are getting steered by random numbers which are thrown in my program! For example: Number 1: meens moving the box positively on the x axis, Number 2: move the box negatively on x axis etc.)
- I want to watch them from a third person perspective (i dont want to be “inside the box”)
I am a complete newbie in using the JMonkeyEngine and as a first step I took the code example from the collision detection beginner tutorial as base.
[java]import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
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.AmbientLight;
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.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
public class SEMain extends SimpleApplication
implements ActionListener {
private Spatial sceneModel;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private boolean move_box_x_pos = false, move_box_x_neg = false, move_box_z_pos = false, move_box_z_neg = false;
private Geometry my_box;
public static void main(String[] args) {
SEMain app = new SEMain();
app.start();
}
public void simpleInitApp() {
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
flyCam.setMoveSpeed(100);
setUpKeys();
setUpLight();
// We load the scene from the zip file and adjust its size.
assetManager.registerLocator(“town.zip”, ZipLocator.class);
sceneModel = assetManager.loadModel(“main.scene”);
sceneModel.setLocalScale(2f);
CollisionShape sceneShape =
CollisionShapeFactory.createMeshShape((Node) sceneModel);
landscape = new RigidBodyControl(sceneShape, 0);
sceneModel.addControl(landscape);
Box b = new Box( new Vector3f(4,10,4), 2,2,2);
my_box = new Geometry(“mybox”,b);
Material m = new Material(assetManager,“Common/MatDefs/Misc/Unshaded.j3md”);
m.setColor(“Color”, ColorRGBA.Green);
my_box.setMaterial(m);
rootNode.attachChild(sceneModel);
rootNode.attachChild(my_box);
bulletAppState.getPhysicsSpace().add(landscape);
//bulletAppState.getPhysicsSpace().add(my_box); //adding mybox to physicsspace… does not work (causes NullpointerException)
}
private void setUpLight() {
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al);
DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
rootNode.addLight(dl);
}
/** We over-write some navigational key mappings here, so we can
- add physics-controlled walking and jumping: /
private void setUpKeys() {
//Input mappings for my purposes
inputManager.addMapping("move_box_x_neg", new KeyTrigger(KeyInput.KEY_F));
inputManager.addMapping("move_box_x_pos", new KeyTrigger(KeyInput.KEY_H));
inputManager.addMapping("move_box_z_pos", new KeyTrigger(KeyInput.KEY_T));
inputManager.addMapping("move_box_z_neg", new KeyTrigger(KeyInput.KEY_G));
inputManager.addListener(this, "move_box_x_pos");
inputManager.addListener(this, "move_box_x_neg");
inputManager.addListener(this, "move_box_z_pos");
inputManager.addListener(this, "move_box_z_neg");
}
//save the user input in boolean variables (analogously to the tutorial)
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("move_box_x_pos")) {
move_box_x_pos = value;
} else if (binding.equals("move_box_x_neg")) {
move_box_x_neg = value;
} else if (binding.equals("move_box_z_pos")) {
move_box_z_pos = value;
} else if (binding.equals("move_box_z_neg")) {
move_box_z_neg = value;
}
}
@Override
public void simpleUpdate(float tpf) {
Vector3f position = ((Box)my_box.getMesh()).getCenter(); // getting the center of my box
//add a vector to the center position yealding the "new position"
if (move_box_x_pos) { position.addLocal(new Vector3f(-10tpf,0,0)); }
if (move_box_x_neg) { position.addLocal(new Vector3f(10tpf,0,0)); }
if (move_box_z_pos) { position.addLocal(new Vector3f(0,0,10tpf)); }
if (move_box_z_neg) { position.addLocal(new Vector3f(0,0,-10*tpf)); }
Box b2 = new Box(position,2,2,2); //create new box at the "new position"
my_box.setMesh(b2); //set the mesh
System.out.println("Cam:"+cam.getLocation());
System.out.println("my_box:"+((Box)my_box.getMesh()).getCenter());
}
}[/java]
I did the following steps:
- I removed the “CharacterControl player” things from the code and added a Geometry “my_box” to the scene
- I modified the steering operations to my purposes
If one executes thie code one will get a green box in the (town-)scene which can be steered by the TFGH-Buttons (and the cam by WASD)
As you can see in the update-function I steer the box by
- getting the Mesh of the Geometry,
- getting the Meshs position
- constructing a new Mesh with another position
- setting the new Mesh as Mesh of the geometry
Now my questions:
- Is this the right way I am going for my purposes?
- How can I enable collision detection and physics for this box? (//bulletAppState.getPhysicsSpace().add(my_box); //adding mybox to physicsspace… does not work (causes NullpointerException)
- How can I steer it with “random numbers”? (Binding keyinput to strings using input manager is nice… but i think i cannot use that technique in this case)
- my_box should also have some more “intelligence”… for example the my_box shell be able to read color values and light values from the scene. I think i could easily subclass the geometry class by a “MyBox” class and putting the intelligence there… is that a recommended usage of the engine?
Thanks in advance.