Aug 31, 2014

40. Collisions

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:


No comments:

Post a Comment