Collisions of 3D objects with an invisible line, whose origin and direction we can set, can be tested.
In simpleInitApp() we call makeBoxes() which sets up our scene.
// *** 1. Start (Call function to create 64 boxes) makeBoxes(4,4,4); // *** 1. End
The Default Text is used to write status text such as number of boxes remaining.
// *** 2. Start (Text) guiNode.detachAllChildren(); BitmapFont font = assetManager.loadFont( "Interface/Fonts/Default.fnt"); statusText = new BitmapText(font, false); statusText.setSize(font.getCharSet().getRenderedSize()); statusText.setLocalTranslation(20, 40+statusText.getLineHeight(), 0); statusText.scale(3); statusText.setColor(ColorRGBA.Green); guiNode.attachChild(statusText); // *** 2. End
The invisible ray goes from camera location, in the direction of camera, and which is also the view direction. If any boxes are in sight and they are close enough, they are removed.
// *** 3. Start (Collisions) CollisionResults results = new CollisionResults(); // empty results Ray ray = new Ray(cam.getLocation(), cam.getDirection()); // camera boxesNode.collideWith(ray, results); // get results if (results.size() > 0) { Geometry closest = results. getClosestCollision().getGeometry(); // nearest box float dist = results.getClosestCollision(). getDistance(); // distance to nearest box String nameClosest = closest.getName(); // name of nearest box System.out.println("The closest box has the name " + nameClosest + " and it is " + dist + " units away."); if (dist<10f) { // close enough will disappear System.out.println("---->And I am gone"); boxesNode.detachChild(closest); } int num = boxesNode.getQuantity(); // boxes left if (num==0) { // no more boxes System.out.println("You win!!!"); statusText.setText("You win!!!"); } else { // boxes left is nonzero System.out.println("There are " + num + " boxes left"); statusText.setText("There are " + num + " boxes left"); } } // *** 3. End
In the makeBoxes, we create a number of adjoining boxes depending on the parameters.
// *** 4. Start (create M*N*P boxes) int i,j,k; boxesNode = new Node("boxes"); Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); mat.setBoolean("UseMaterialColors",true); mat.setColor("Diffuse",ColorRGBA.Blue); mat.setColor("Specular",ColorRGBA.White); for (i=0; i<M;i++) { for (j = 0; j<N; j++ ) { for (k = 0; k<P; k++) { Box b = new Box(1f,1f,1f); Geometry gb = new Geometry("b"+i+","+j+","+k,b); gb.setMaterial(mat); gb.setLocalTranslation(2*i,2*j,2*k-5); boxesNode.attachChild(gb); } } } // *** 4. End
// JMonkey40.java package mygame; import com.jme3.app.SimpleApplication; import com.jme3.collision.CollisionResults; import com.jme3.font.BitmapFont; import com.jme3.font.BitmapText; import com.jme3.light.DirectionalLight; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.Ray; import com.jme3.math.Vector3f; import com.jme3.renderer.RenderManager; import com.jme3.scene.Geometry; import com.jme3.scene.Node; import com.jme3.scene.shape.Box; import com.jme3.system.AppSettings; public class JMonkey40 extends SimpleApplication { public static void main(String[] args) { AppSettings settings = new AppSettings(true); settings.setFrameRate(60); settings.setTitle("Remove the Boxes !"); JMonkey40 app = new JMonkey40(); app.setSettings(settings); app.start(); } private Node boxesNode; private BitmapText statusText; @Override public void simpleInitApp() { viewPort.setBackgroundColor(ColorRGBA.Gray); setDisplayFps(false); setDisplayStatView(false); // *** 1. Start (Call function to create 64 boxes) makeBoxes(4,4,4); // *** 1. End // *** 2. Start (Text) guiNode.detachAllChildren(); BitmapFont font = assetManager.loadFont( "Interface/Fonts/Default.fnt"); statusText = new BitmapText(font, false); statusText.setSize(font.getCharSet().getRenderedSize()); statusText.setLocalTranslation(20, 40+statusText.getLineHeight(), 0); statusText.scale(3); statusText.setColor(ColorRGBA.Green); guiNode.attachChild(statusText); // *** 2. End } @Override public void simpleUpdate(float tpf) { // *** 3. Start (Collisions) CollisionResults results = new CollisionResults(); // empty results Ray ray = new Ray(cam.getLocation(), cam.getDirection()); // camera boxesNode.collideWith(ray, results); // get results if (results.size() > 0) { Geometry closest = results. getClosestCollision().getGeometry(); // nearest box float dist = results.getClosestCollision(). getDistance(); // distance to nearest box String nameClosest = closest.getName(); // name of nearest box System.out.println("The closest box has the name " + nameClosest + " and it is " + dist + " units away."); if (dist<10f) { // close enough will disappear System.out.println("---->And I am gone"); boxesNode.detachChild(closest); } int num = boxesNode.getQuantity(); // boxes left if (num==0) { // no more boxes System.out.println("You win!!!"); statusText.setText("You win!!!"); } else { // boxes left is nonzero System.out.println("There are " + num + " boxes left"); statusText.setText("There are " + num + " boxes left"); } } // *** 3. End } @Override public void simpleRender(RenderManager rm) { } private void makeBoxes(int M, int N, int P) { // *** 4. Start (create M*N*P boxes) int i,j,k; boxesNode = new Node("boxes"); Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); mat.setBoolean("UseMaterialColors",true); mat.setColor("Diffuse",ColorRGBA.Blue); mat.setColor("Specular",ColorRGBA.White); for (i=0; i<M;i++) { for (j = 0; j<N; j++ ) { for (k = 0; k<P; k++) { Box b = new Box(1f,1f,1f); Geometry gb = new Geometry("b"+i+","+j+","+k,b); gb.setMaterial(mat); gb.setLocalTranslation(2*i,2*j,2*k-5); boxesNode.attachChild(gb); } } } // *** 4. End // sun1 DirectionalLight sun1 = new DirectionalLight(); sun1.setDirection((new Vector3f(-0.5f, -0.5f, -0.5f)).normalizeLocal()); sun1.setColor(ColorRGBA.White); rootNode.addLight(sun1); // sun2 DirectionalLight sun2 = new DirectionalLight(); sun2.setDirection((new Vector3f(0.5f, 0.5f, 0.5f)).normalizeLocal()); sun2.setColor(ColorRGBA.Pink); rootNode.addLight(sun2); rootNode.attachChild(boxesNode); } }
Output: