jMonkeyEngine 3.0 Beginner’s Guide
上QQ阅读APP看书,第一时间看更新

Time for action – chase all the cubes!

The other cubes are mightily impressed by your new-found cube chasing skills. Can you change the code sample so that you can pick which cube you want to chase, simply by looking at it? Use the ray casting method that you learned in the earlier target picking examples!

  1. Since you will detect cubes with the help of ray casting, create a class field for the ray object.
    private Ray ray = new Ray();
  2. Completely remove the code pertaining to scaredCube—a real cube chaser doesn't need an extra class field to pick a cube.
  3. Put the following code in the simpleUpdate() method loop to keep the ray up-to-date. Use the ray.setOrigin(cam.getLocation()) method and the ray.setDirection(cam.getDirection()) method to aim the ray in the direction of the camera. Identify collisions and pick the closest geometry as the target. Test the distance and change the target's location, just as before.
    public void simpleUpdate(float tpf) {
        CollisionResults results = new CollisionResults();
        ray.setOrigin(cam.getLocation());
        ray.setDirection(cam.getDirection());
        rootNode.collideWith(ray, results);
        if (results.size() > 0) {
            Geometry target = results.getClosestCollision().getGeometry();
            if (cam.getLocation().
                distance(target.getLocalTranslation()) < 10) {
                target.move(cam.getDirection());
            }
        }
    }

Run the sample, navigate through the scene, and look around. Suddenly, none of the cubes can withstand your awe-inspiring gaze!

What just happened?

You cleverly combined two things that you have just learned. The ray casting algorithm is not limited to input listeners—you can just as well use the simpleUpdate() method loop to cast the ray, identify current collisions with the scene graph, and interact with the targets.

As your game grows more complex, you will find yourself putting more and more conditionals and actions in the simpleUpdate() method. But a long sequence of tests in one method of one class is not exactly an object-oriented solution—this will soon be a pain to maintain. Of course it's fine to experiment with new game mechanics in the simpleUpdate() method during development, just like we did with the ray casting algorithm. When a code block in the simpleUpdate() method does what it is supposed to do, consider encapsulating it as abstract, reusable behavior. Your game interactions will be much cleaner if you move behaviors into dedicated classes, so-called controls.