
Time for action – you are the CubeChaser
Let's do something more interactive than just look at rotating cubes. Can you write code that lets you chase one of the cubes? By chase we mean, if the camera moves closer than 10 WU to this cube, the cube should move away from the camera.
- Make another copy of the
BasicGame
object'sMain.java
template. - Rename the copy to
CubeChaser.java
. Remember to also refactor the first line of themain()
method to the following:CubeChaser app = new CubeChaser();
- Delete the blue cube and copy the
myBox()
convenience method from one of the previous target picking examples. Don't forget to copy themesh
class field. - Add a
makeCubes(40);
call to thesimpleInitApp()
method and fill the scene with 40 randomly positioned and randomly colored cubes. Use the built-in methodFastMath.nextRandomInt(min,max)
(fromcom.jme3.math
) to generate random coordinates in the interval betweenmin
andmax
.private void makeCubes(int number) { for (int i = 0; i < number; i++) { // randomize 3D coordinates Vector3f loc = new Vector3f( FastMath.nextRandomInt(-20, 20), FastMath.nextRandomInt(-20, 20), FastMath.nextRandomInt(-20, 20)); rootNode.attachChild( myBox("Cube" + i, loc, ColorRGBA.randomColor())); } }
- Create a white cube geometry,
scaredCube
, as a class field, and position it in the origin.private Geometry scaredCube; ... public void simpleInitApp() { makeCubes(40); scaredCube = myBox("Scared Cube", Vector3f.ZERO, ColorRGBA.White); rootNode.attachChild(scaredCube); }
How would you write code that constantly monitors the distance between the camera location and the location of the
scaredCube
object? You write these kinds of tests in thesimpleUpdate(float tpf)
method. - Use the
vector1.distance(vector2)
method for the distance test. You get current object coordinates by calling thecam.getLocation()
andcube.getLocalTranslation()
methods.public void simpleUpdate(float tpf) { System.out.println("Distance: "+ cam.getLocation().distance(scaredCube.getLocalTranslation())); }
- Modify this code so that it tests whether the distance is less than 10 WU. If yes, then move the scared cube away from you, that is, in the direction that the camera is facing.
public void simpleUpdate(float tpf) { ... if (cam.getLocation().distance(scaredCube.getLocalTranslation()) < 10) { scaredCube.move(cam.getDirection()); } }
Run the class and use the W, A, S, and D keys and the mouse to navigate through the cube-filled scene. Keep an eye on the white cube!
Tip
If you feel you are moving too slow, you can speed up the default camera. Add the following command somewhere in the simpleInitApp()
method:
flyCam.setMoveSpeed(100f);
What just happened?
When you run this class you see that the simpleUpdate()
method prints a lot of output to the console. The current camera location and the cube location are polled in every frame, and their distance is recalculated and printed. The simpleUpdate()
method ensures that your test always returns the latest results, even while you and the scared cube are moving wildly through the scene.
If you back away and move around the cube—sneak up on it from behind, so to speak—you can chase it back into the cluster of cubes. Just like the camera location, the camera direction inside the simpleUpdate()
method returns an updated value every frame. The vector points in the new direction while you navigate the camera around the cube, so that you can chase the cube back.
The simpleUpdate()
method is one way to hook code directly into the main loop. Everything in this method is executed repeatedly, as fast as possible, as long as the game runs. (Hint: Be careful when creating new objects here!) Just like the simpleInitApp()
method, you never call the simpleUpdate()
method yourself. You only implement the method body, and jMonkeyEngine takes care of executing it.