Home | History | Annotate | Download | only in bullet
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine All rights reserved. <p/>
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are met:
      5  *
      6  * * Redistributions of source code must retain the above copyright notice,
      7  * this list of conditions and the following disclaimer. <p/> * Redistributions
      8  * in binary form must reproduce the above copyright notice, this list of
      9  * conditions and the following disclaimer in the documentation and/or other
     10  * materials provided with the distribution. <p/> * Neither the name of
     11  * 'jMonkeyEngine' nor the names of its contributors may be used to endorse or
     12  * promote products derived from this software without specific prior written
     13  * permission. <p/> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     14  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
     15  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     16  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 package jme3test.bullet;
     26 
     27 import com.jme3.app.SimpleApplication;
     28 import com.jme3.bullet.BulletAppState;
     29 import com.jme3.bullet.PhysicsSpace;
     30 import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
     31 import com.jme3.bullet.control.CharacterControl;
     32 import com.jme3.input.KeyInput;
     33 import com.jme3.input.MouseInput;
     34 import com.jme3.input.controls.ActionListener;
     35 import com.jme3.input.controls.KeyTrigger;
     36 import com.jme3.input.controls.MouseButtonTrigger;
     37 import com.jme3.math.Vector3f;
     38 import com.jme3.renderer.RenderManager;
     39 import com.jme3.scene.CameraNode;
     40 import com.jme3.scene.Node;
     41 import com.jme3.scene.Spatial;
     42 import com.jme3.scene.control.CameraControl.ControlDirection;
     43 
     44 /**
     45  * A walking physical character followed by a 3rd person camera. (No animation.)
     46  * @author normenhansen, zathras
     47  */
     48 public class TestPhysicsCharacter extends SimpleApplication implements ActionListener {
     49 
     50   private BulletAppState bulletAppState;
     51   private CharacterControl physicsCharacter;
     52   private Node characterNode;
     53   private CameraNode camNode;
     54   boolean rotate = false;
     55   private Vector3f walkDirection = new Vector3f(0,0,0);
     56   private Vector3f viewDirection = new Vector3f(0,0,0);
     57   boolean leftStrafe = false, rightStrafe = false, forward = false, backward = false,
     58           leftRotate = false, rightRotate = false;
     59 
     60   public static void main(String[] args) {
     61     TestPhysicsCharacter app = new TestPhysicsCharacter();
     62     app.start();
     63   }
     64 
     65     private void setupKeys() {
     66         inputManager.addMapping("Strafe Left",
     67                 new KeyTrigger(KeyInput.KEY_Q),
     68                 new KeyTrigger(KeyInput.KEY_Z));
     69         inputManager.addMapping("Strafe Right",
     70                 new KeyTrigger(KeyInput.KEY_E),
     71                 new KeyTrigger(KeyInput.KEY_X));
     72         inputManager.addMapping("Rotate Left",
     73                 new KeyTrigger(KeyInput.KEY_A),
     74                 new KeyTrigger(KeyInput.KEY_LEFT));
     75         inputManager.addMapping("Rotate Right",
     76                 new KeyTrigger(KeyInput.KEY_D),
     77                 new KeyTrigger(KeyInput.KEY_RIGHT));
     78         inputManager.addMapping("Walk Forward",
     79                 new KeyTrigger(KeyInput.KEY_W),
     80                 new KeyTrigger(KeyInput.KEY_UP));
     81         inputManager.addMapping("Walk Backward",
     82                 new KeyTrigger(KeyInput.KEY_S),
     83                 new KeyTrigger(KeyInput.KEY_DOWN));
     84         inputManager.addMapping("Jump",
     85                 new KeyTrigger(KeyInput.KEY_SPACE),
     86                 new KeyTrigger(KeyInput.KEY_RETURN));
     87         inputManager.addMapping("Shoot",
     88                 new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
     89         inputManager.addListener(this, "Strafe Left", "Strafe Right");
     90         inputManager.addListener(this, "Rotate Left", "Rotate Right");
     91         inputManager.addListener(this, "Walk Forward", "Walk Backward");
     92         inputManager.addListener(this, "Jump", "Shoot");
     93     }
     94   @Override
     95   public void simpleInitApp() {
     96     // activate physics
     97     bulletAppState = new BulletAppState();
     98     stateManager.attach(bulletAppState);
     99 
    100     // init a physical test scene
    101     PhysicsTestHelper.createPhysicsTestWorldSoccer(rootNode, assetManager, bulletAppState.getPhysicsSpace());
    102     setupKeys();
    103 
    104     // Add a physics character to the world
    105     physicsCharacter = new CharacterControl(new CapsuleCollisionShape(0.5f, 1.8f), .1f);
    106     physicsCharacter.setPhysicsLocation(new Vector3f(0, 1, 0));
    107     characterNode = new Node("character node");
    108     Spatial model = assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
    109     model.scale(0.25f);
    110     characterNode.addControl(physicsCharacter);
    111     getPhysicsSpace().add(physicsCharacter);
    112     rootNode.attachChild(characterNode);
    113     characterNode.attachChild(model);
    114 
    115     // set forward camera node that follows the character
    116     camNode = new CameraNode("CamNode", cam);
    117     camNode.setControlDir(ControlDirection.SpatialToCamera);
    118     camNode.setLocalTranslation(new Vector3f(0, 1, -5));
    119     camNode.lookAt(model.getLocalTranslation(), Vector3f.UNIT_Y);
    120     characterNode.attachChild(camNode);
    121 
    122     //disable the default 1st-person flyCam (don't forget this!!)
    123     flyCam.setEnabled(false);
    124 
    125   }
    126 
    127    @Override
    128     public void simpleUpdate(float tpf) {
    129         Vector3f camDir = cam.getDirection().mult(0.2f);
    130         Vector3f camLeft = cam.getLeft().mult(0.2f);
    131         camDir.y = 0;
    132         camLeft.y = 0;
    133         viewDirection.set(camDir);
    134         walkDirection.set(0, 0, 0);
    135         if (leftStrafe) {
    136             walkDirection.addLocal(camLeft);
    137         } else
    138         if (rightStrafe) {
    139             walkDirection.addLocal(camLeft.negate());
    140         }
    141         if (leftRotate) {
    142             viewDirection.addLocal(camLeft.mult(0.02f));
    143         } else
    144         if (rightRotate) {
    145             viewDirection.addLocal(camLeft.mult(0.02f).negate());
    146         }
    147         if (forward) {
    148             walkDirection.addLocal(camDir);
    149         } else
    150         if (backward) {
    151             walkDirection.addLocal(camDir.negate());
    152         }
    153         physicsCharacter.setWalkDirection(walkDirection);
    154         physicsCharacter.setViewDirection(viewDirection);
    155     }
    156 
    157     public void onAction(String binding, boolean value, float tpf) {
    158         if (binding.equals("Strafe Left")) {
    159             if (value) {
    160                 leftStrafe = true;
    161             } else {
    162                 leftStrafe = false;
    163             }
    164         } else if (binding.equals("Strafe Right")) {
    165             if (value) {
    166                 rightStrafe = true;
    167             } else {
    168                 rightStrafe = false;
    169             }
    170         } else if (binding.equals("Rotate Left")) {
    171             if (value) {
    172                 leftRotate = true;
    173             } else {
    174                 leftRotate = false;
    175             }
    176         } else if (binding.equals("Rotate Right")) {
    177             if (value) {
    178                 rightRotate = true;
    179             } else {
    180                 rightRotate = false;
    181             }
    182         } else if (binding.equals("Walk Forward")) {
    183             if (value) {
    184                 forward = true;
    185             } else {
    186                 forward = false;
    187             }
    188         } else if (binding.equals("Walk Backward")) {
    189             if (value) {
    190                 backward = true;
    191             } else {
    192                 backward = false;
    193             }
    194         } else if (binding.equals("Jump")) {
    195             physicsCharacter.jump();
    196         }
    197     }
    198 
    199   private PhysicsSpace getPhysicsSpace() {
    200     return bulletAppState.getPhysicsSpace();
    201   }
    202 
    203   @Override
    204   public void simpleRender(RenderManager rm) {
    205     //TODO: add render code
    206   }
    207 }
    208