Home | History | Annotate | Download | only in helloworld
      1 /**
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *  notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *  notice, this list of conditions and the following disclaimer in the
     14  *  documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *  may be used to endorse or promote products derived from this software
     18  *  without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 package jme3test.helloworld;
     34 
     35 import com.jme3.app.SimpleApplication;
     36 import com.jme3.asset.TextureKey;
     37 import com.jme3.bullet.BulletAppState;
     38 import com.jme3.bullet.control.RigidBodyControl;
     39 import com.jme3.font.BitmapText;
     40 import com.jme3.input.MouseInput;
     41 import com.jme3.input.controls.ActionListener;
     42 import com.jme3.input.controls.MouseButtonTrigger;
     43 import com.jme3.material.Material;
     44 import com.jme3.math.Vector2f;
     45 import com.jme3.math.Vector3f;
     46 import com.jme3.scene.Geometry;
     47 import com.jme3.scene.shape.Box;
     48 import com.jme3.scene.shape.Sphere;
     49 import com.jme3.scene.shape.Sphere.TextureMode;
     50 import com.jme3.texture.Texture;
     51 import com.jme3.texture.Texture.WrapMode;
     52 
     53 /**
     54  * Example 12 - how to give objects physical properties so they bounce and fall.
     55  * @author base code by double1984, updated by zathras
     56  */
     57 public class HelloPhysics extends SimpleApplication {
     58 
     59   public static void main(String args[]) {
     60     HelloPhysics app = new HelloPhysics();
     61     app.start();
     62   }
     63 
     64   /** Prepare the Physics Application State (jBullet) */
     65   private BulletAppState bulletAppState;
     66 
     67   /** Prepare Materials */
     68   Material wall_mat;
     69   Material stone_mat;
     70   Material floor_mat;
     71 
     72   /** Prepare geometries and physical nodes for bricks and cannon balls. */
     73   private RigidBodyControl    brick_phy;
     74   private static final Box    box;
     75   private RigidBodyControl    ball_phy;
     76   private static final Sphere sphere;
     77   private RigidBodyControl    floor_phy;
     78   private static final Box    floor;
     79 
     80   /** dimensions used for bricks and wall */
     81   private static final float brickLength = 0.48f;
     82   private static final float brickWidth  = 0.24f;
     83   private static final float brickHeight = 0.12f;
     84 
     85   static {
     86     /** Initialize the cannon ball geometry */
     87     sphere = new Sphere(32, 32, 0.4f, true, false);
     88     sphere.setTextureMode(TextureMode.Projected);
     89     /** Initialize the brick geometry */
     90     box = new Box(Vector3f.ZERO, brickLength, brickHeight, brickWidth);
     91     box.scaleTextureCoordinates(new Vector2f(1f, .5f));
     92     /** Initialize the floor geometry */
     93     floor = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
     94     floor.scaleTextureCoordinates(new Vector2f(3, 6));
     95   }
     96 
     97   @Override
     98   public void simpleInitApp() {
     99     /** Set up Physics Game */
    100     bulletAppState = new BulletAppState();
    101     stateManager.attach(bulletAppState);
    102     //bulletAppState.getPhysicsSpace().enableDebug(assetManager);
    103     /** Configure cam to look at scene */
    104     cam.setLocation(new Vector3f(0, 4f, 6f));
    105     cam.lookAt(new Vector3f(2, 2, 0), Vector3f.UNIT_Y);
    106     /** Initialize the scene, materials, inputs, and physics space */
    107     initInputs();
    108     initMaterials();
    109     initWall();
    110     initFloor();
    111     initCrossHairs();
    112   }
    113 
    114   /** Add InputManager action: Left click triggers shooting. */
    115   private void initInputs() {
    116     inputManager.addMapping("shoot",
    117             new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
    118     inputManager.addListener(actionListener, "shoot");
    119   }
    120 
    121   /**
    122    * Every time the shoot action is triggered, a new cannon ball is produced.
    123    * The ball is set up to fly from the camera position in the camera direction.
    124    */
    125   private ActionListener actionListener = new ActionListener() {
    126     public void onAction(String name, boolean keyPressed, float tpf) {
    127       if (name.equals("shoot") && !keyPressed) {
    128         makeCannonBall();
    129       }
    130     }
    131   };
    132 
    133   /** Initialize the materials used in this scene. */
    134   public void initMaterials() {
    135     wall_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    136     TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");
    137     key.setGenerateMips(true);
    138     Texture tex = assetManager.loadTexture(key);
    139     wall_mat.setTexture("ColorMap", tex);
    140 
    141     stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    142     TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
    143     key2.setGenerateMips(true);
    144     Texture tex2 = assetManager.loadTexture(key2);
    145     stone_mat.setTexture("ColorMap", tex2);
    146 
    147     floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    148     TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg");
    149     key3.setGenerateMips(true);
    150     Texture tex3 = assetManager.loadTexture(key3);
    151     tex3.setWrap(WrapMode.Repeat);
    152     floor_mat.setTexture("ColorMap", tex3);
    153   }
    154 
    155   /** Make a solid floor and add it to the scene. */
    156   public void initFloor() {
    157     Geometry floor_geo = new Geometry("Floor", floor);
    158     floor_geo.setMaterial(floor_mat);
    159     floor_geo.setLocalTranslation(0, -0.1f, 0);
    160     this.rootNode.attachChild(floor_geo);
    161     /* Make the floor physical with mass 0.0f! */
    162     floor_phy = new RigidBodyControl(0.0f);
    163     floor_geo.addControl(floor_phy);
    164     bulletAppState.getPhysicsSpace().add(floor_phy);
    165   }
    166 
    167   /** This loop builds a wall out of individual bricks. */
    168   public void initWall() {
    169     float startpt = brickLength / 4;
    170     float height = 0;
    171     for (int j = 0; j < 15; j++) {
    172       for (int i = 0; i < 6; i++) {
    173         Vector3f vt =
    174          new Vector3f(i * brickLength * 2 + startpt, brickHeight + height, 0);
    175         makeBrick(vt);
    176       }
    177       startpt = -startpt;
    178       height += 2 * brickHeight;
    179     }
    180   }
    181 
    182   /** This method creates one individual physical brick. */
    183   public void makeBrick(Vector3f loc) {
    184     /** Create a brick geometry and attach to scene graph. */
    185     Geometry brick_geo = new Geometry("brick", box);
    186     brick_geo.setMaterial(wall_mat);
    187     rootNode.attachChild(brick_geo);
    188     /** Position the brick geometry  */
    189     brick_geo.setLocalTranslation(loc);
    190     /** Make brick physical with a mass > 0.0f. */
    191     brick_phy = new RigidBodyControl(2f);
    192     /** Add physical brick to physics space. */
    193     brick_geo.addControl(brick_phy);
    194     bulletAppState.getPhysicsSpace().add(brick_phy);
    195   }
    196 
    197   /** This method creates one individual physical cannon ball.
    198    * By defaul, the ball is accelerated and flies
    199    * from the camera position in the camera direction.*/
    200    public void makeCannonBall() {
    201     /** Create a cannon ball geometry and attach to scene graph. */
    202     Geometry ball_geo = new Geometry("cannon ball", sphere);
    203     ball_geo.setMaterial(stone_mat);
    204     rootNode.attachChild(ball_geo);
    205     /** Position the cannon ball  */
    206     ball_geo.setLocalTranslation(cam.getLocation());
    207     /** Make the ball physcial with a mass > 0.0f */
    208     ball_phy = new RigidBodyControl(1f);
    209     /** Add physical ball to physics space. */
    210     ball_geo.addControl(ball_phy);
    211     bulletAppState.getPhysicsSpace().add(ball_phy);
    212     /** Accelerate the physcial ball to shoot it. */
    213     ball_phy.setLinearVelocity(cam.getDirection().mult(25));
    214   }
    215 
    216   /** A plus sign used as crosshairs to help the player with aiming.*/
    217   protected void initCrossHairs() {
    218     guiNode.detachAllChildren();
    219     guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
    220     BitmapText ch = new BitmapText(guiFont, false);
    221     ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
    222     ch.setText("+");        // fake crosshairs :)
    223     ch.setLocalTranslation( // center
    224       settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
    225       settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
    226     guiNode.attachChild(ch);
    227   }
    228 }
    229