@ -1,33 +1,26 @@
/ *
* Copyright ( c ) 2009 - 2010 jMonkeyEngine
* All rights reserved .
*
* Copyright ( c ) 2009 - 2010 jMonkeyEngine All rights reserved . < p / >
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are
* met :
*
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
*
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* * Neither the name of ' jMonkeyEngine ' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED
* TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* modification , are permitted provided that the following conditions are met :
*
* * Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer . < p / > * Redistributions
* in binary form must reproduce the above copyright notice , this list of
* conditions and the following disclaimer in the documentation and / or other
* materials provided with the distribution . < p / > * Neither the name of
* ' jMonkeyEngine ' nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written
* permission . < p / > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT
* NOT LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL ,
* EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO ,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ;
* OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY ,
* WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR
* OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
package jme3test.bullet ;
@ -35,123 +28,180 @@ import com.jme3.bullet.BulletAppState;
import com.jme3.app.SimpleApplication ;
import com.jme3.bullet.PhysicsSpace ;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape ;
import com.jme3.bullet.collision.shapes.SphereCollisionShape ;
import com.jme3.bullet.control.CharacterControl ;
import com.jme3.input.KeyInput ;
import com.jme3.input.MouseInput ;
import com.jme3.input.controls.ActionListener ;
import com.jme3.input.controls.KeyTrigger ;
import com.jme3.input.controls.MouseButtonTrigger ;
import com.jme3.material.Material ;
import com.jme3.math.Vector3f ;
import com.jme3.renderer.RenderManager ;
import com.jme3.scene.CameraNode ;
import com.jme3.scene.Node ;
import com.jme3.scene.Spatial ;
import com.jme3.scene.shape.Sphere ;
import com.jme3.scene.shape.Sphere.TextureMode ;
import com.jme3.scene.control.CameraControl.ControlDirection ;
/ * *
*
* @author normenhansen
* A walking physical character followed by a 3rd person camera . ( No animation . )
* @author normenhansen , zathras
* /
public class TestPhysicsCharacter extends SimpleApplication implements ActionListener {
private BulletAppState bulletAppState ;
private CharacterControl physicsCharacter ;
private Vector3f walkDirection = new Vector3f ( ) ;
private Material mat ;
private Sphere bullet ;
private SphereCollisionShape bulletCollisionShape ;
private BulletAppState bulletAppState ;
private CharacterControl physicsCharacter ;
private Node characterNode ;
private CameraNode camNode ;
boolean rotate = false ;
private Vector3f walkDirection = new Vector3f ( 0 , 0 , 0 ) ;
private Vector3f viewDirection = new Vector3f ( 0 , 0 , 0 ) ;
boolean leftStrafe = false , rightStrafe = false , forward = false , backward = false ,
leftRotate = false , rightRotate = false ;
public static void main ( String [ ] args ) {
TestPhysicsCharacter app = new TestPhysicsCharacter ( ) ;
app . start ( ) ;
}
public static void main ( String [ ] args ) {
TestPhysicsCharacter app = new TestPhysicsCharacter ( ) ;
app . start ( ) ;
}
private void setupKeys ( ) {
inputManager . addMapping ( "Lefts" , new KeyTrigger ( KeyInput . KEY_H ) ) ;
inputManager . addMapping ( "Rights" , new KeyTrigger ( KeyInput . KEY_K ) ) ;
inputManager . addMapping ( "Ups" , new KeyTrigger ( KeyInput . KEY_U ) ) ;
inputManager . addMapping ( "Downs" , new KeyTrigger ( KeyInput . KEY_J ) ) ;
inputManager . addMapping ( "Space" , new KeyTrigger ( KeyInput . KEY_SPACE ) ) ;
inputManager . addMapping ( "shoot" , new MouseButtonTrigger ( MouseInput . BUTTON_LEFT ) ) ;
inputManager . addListener ( this , "shoot" ) ;
inputManager . addListener ( this , "Lefts" ) ;
inputManager . addListener ( this , "Rights" ) ;
inputManager . addListener ( this , "Ups" ) ;
inputManager . addListener ( this , "Downs" ) ;
inputManager . addListener ( this , "Space" ) ;
inputManager . addMapping ( "gc" , new KeyTrigger ( KeyInput . KEY_X ) ) ;
inputManager . addListener ( this , "gc" ) ;
inputManager . addMapping ( "Strafe Left" ,
new KeyTrigger ( KeyInput . KEY_Q ) ,
new KeyTrigger ( KeyInput . KEY_Z ) ) ;
inputManager . addMapping ( "Strafe Right" ,
new KeyTrigger ( KeyInput . KEY_E ) ,
new KeyTrigger ( KeyInput . KEY_X ) ) ;
inputManager . addMapping ( "Rotate Left" ,
new KeyTrigger ( KeyInput . KEY_A ) ,
new KeyTrigger ( KeyInput . KEY_LEFT ) ) ;
inputManager . addMapping ( "Rotate Right" ,
new KeyTrigger ( KeyInput . KEY_D ) ,
new KeyTrigger ( KeyInput . KEY_RIGHT ) ) ;
inputManager . addMapping ( "Walk Forward" ,
new KeyTrigger ( KeyInput . KEY_W ) ,
new KeyTrigger ( KeyInput . KEY_UP ) ) ;
inputManager . addMapping ( "Walk Backward" ,
new KeyTrigger ( KeyInput . KEY_S ) ,
new KeyTrigger ( KeyInput . KEY_DOWN ) ) ;
inputManager . addMapping ( "Jump" ,
new KeyTrigger ( KeyInput . KEY_SPACE ) ,
new KeyTrigger ( KeyInput . KEY_RETURN ) ) ;
inputManager . addMapping ( "Shoot" ,
new MouseButtonTrigger ( MouseInput . BUTTON_LEFT ) ) ;
inputManager . addListener ( this , "Strafe Left" , "Strafe Right" ) ;
inputManager . addListener ( this , "Rotate Left" , "Rotate Right" ) ;
inputManager . addListener ( this , "Walk Forward" , "Walk Backward" ) ;
inputManager . addListener ( this , "Jump" , "Shoot" ) ;
}
@Override
public void simpleInitApp ( ) {
// activate physics
bulletAppState = new BulletAppState ( ) ;
stateManager . attach ( bulletAppState ) ;
@Override
public void simpleInitApp ( ) {
bulletAppState = new BulletAppState ( ) ;
stateManager . attach ( bulletAppState ) ;
bullet = new Sphere ( 32 , 32 , 0 . 4f , true , false ) ;
bullet . setTextureMode ( TextureMode . Projected ) ;
bulletCollisionShape = new SphereCollisionShape ( 0 . 4f ) ;
PhysicsTestHelper . createPhysicsTestWorld ( rootNode , assetManager , bulletAppState . getPhysicsSpace ( ) ) ;
// init a physical test scene
PhysicsTestHelper . createPhysicsTestWorldSoccer ( rootNode , assetManager , bulletAppState . getPhysicsSpace ( ) ) ;
setupKeys ( ) ;
setupKeys ( ) ;
// Add a physics character to the world
physicsCharacter = new CharacterControl ( new CapsuleCollisionShape ( 0 . 5f , 1 . 8f ) , . 1f ) ;
physicsCharacter . setPhysicsLocation ( new Vector3f ( 0 , 1 , 0 ) ) ;
characterNode = new Node ( "character node" ) ;
Spatial model = assetManager . loadModel ( "Models/Sinbad/Sinbad.mesh.xml" ) ;
model . scale ( 0 . 25f ) ;
characterNode . addControl ( physicsCharacter ) ;
getPhysicsSpace ( ) . add ( physicsCharacter ) ;
rootNode . attachChild ( characterNode ) ;
characterNode . attachChild ( model ) ;
// Add a physics character to the world
physicsCharacter = new CharacterControl ( new CapsuleCollisionShape ( 0 . 5f , 1 . 8f ) , . 1f ) ;
physicsCharacter . setPhysicsLocation ( new Vector3f ( 3 , 6 , 0 ) ) ;
// set forward camera node that follows the character
camNode = new CameraNode ( "CamNode" , cam ) ;
camNode . setControlDir ( ControlDirection . SpatialToCamera ) ;
camNode . setLocalTranslation ( new Vector3f ( 0 , 1 , - 5 ) ) ;
camNode . lookAt ( model . getLocalTranslation ( ) , Vector3f . UNIT_Y ) ;
characterNode . attachChild ( camNode ) ;
Spatial model = assetManager . loadModel ( "Models/Sinbad/Sinbad.mesh.xml" ) ;
model . scale ( 0 . 25f ) ;
model . addControl ( physicsCharacter ) ;
getPhysicsSpace ( ) . add ( physicsCharacter ) ;
rootNode . attachChild ( model ) ;
}
//disable the default 1st-person flyCam (don't forget this!!)
flyCam . setEnabled ( false ) ;
private PhysicsSpace getPhysicsSpace ( ) {
return bulletAppState . getPhysicsSpace ( ) ;
}
}
@Override
@Override
public void simpleUpdate ( float tpf ) {
Vector3f camDir = cam . getDirection ( ) . mult ( 0 . 2f ) ;
Vector3f camLeft = cam . getLeft ( ) . mult ( 0 . 2f ) ;
camDir . y = 0 ;
camLeft . y = 0 ;
viewDirection . set ( camDir ) ;
walkDirection . set ( 0 , 0 , 0 ) ;
if ( leftStrafe ) {
walkDirection . addLocal ( camLeft ) ;
} else
if ( rightStrafe ) {
walkDirection . addLocal ( camLeft . negate ( ) ) ;
}
if ( leftRotate ) {
viewDirection . addLocal ( camLeft . mult ( 0 . 02f ) ) ;
} else
if ( rightRotate ) {
viewDirection . addLocal ( camLeft . mult ( 0 . 02f ) . negate ( ) ) ;
}
if ( forward ) {
walkDirection . addLocal ( camDir ) ;
} else
if ( backward ) {
walkDirection . addLocal ( camDir . negate ( ) ) ;
}
physicsCharacter . setWalkDirection ( walkDirection ) ;
physicsCharacter . setViewDirection ( walkDirection ) ;
cam . lookAt ( physicsCharacter . getPhysicsLocation ( ) , Vector3f . UNIT_Y ) ;
}
@Override
public void simpleRender ( RenderManager rm ) {
//TODO: add render code
physicsCharacter . setViewDirection ( viewDirection ) ;
}
public void onAction ( String binding , boolean value , float tpf ) {
if ( binding . equals ( "Lefts" ) ) {
if ( binding . equals ( "Strafe Left" ) ) {
if ( value ) {
walkDirection . addLocal ( new Vector3f ( - . 1f , 0 , 0 ) ) ;
leftStrafe = true ;
} else {
walkDirection . addLocal ( new Vector3f ( . 1f , 0 , 0 ) ) ;
leftStrafe = false ;
}
} else if ( binding . equals ( "Rights" ) ) {
} else if ( binding . equals ( "Strafe Right" ) ) {
if ( value ) {
walkDirection . addLocal ( new Vector3f ( . 1f , 0 , 0 ) ) ;
rightStrafe = true ;
} else {
walkDirection . addLocal ( new Vector3f ( - . 1f , 0 , 0 ) ) ;
rightStrafe = false ;
}
} else if ( binding . equals ( "Ups" ) ) {
} else if ( binding . equals ( "Rotate Left " ) ) {
if ( value ) {
walkDirection . addLocal ( new Vector3f ( 0 , 0 , - . 1f ) ) ;
leftRotate = true ;
} else {
walkDirection . addLocal ( new Vector3f ( 0 , 0 , . 1f ) ) ;
leftRotate = false ;
}
} else if ( binding . equals ( "Downs " ) ) {
} else if ( binding . equals ( "Rotate Right " ) ) {
if ( value ) {
walkDirection . addLocal ( new Vector3f ( 0 , 0 , . 1f ) ) ;
rightRotate = true ;
} else {
walkDirection . addLocal ( new Vector3f ( 0 , 0 , - . 1f ) ) ;
rightRotate = false ;
}
} else if ( binding . equals ( "Space" ) ) {
} else if ( binding . equals ( "Walk Forward" ) ) {
if ( value ) {
forward = true ;
} else {
forward = false ;
}
} else if ( binding . equals ( "Walk Backward" ) ) {
if ( value ) {
backward = true ;
} else {
backward = false ;
}
} else if ( binding . equals ( "Jump" ) ) {
physicsCharacter . jump ( ) ;
}
if ( binding . equals ( "gc" ) & & ! value ) {
System . gc ( ) ;
}
}
private PhysicsSpace getPhysicsSpace ( ) {
return bulletAppState . getPhysicsSpace ( ) ;
}
@Override
public void simpleRender ( RenderManager rm ) {
//TODO: add render code
}
}