Ok, I have this code:
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import com.game.camera.CharacterChaser;
import com.game.resources.ResourceFile;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.input.thirdperson.ThirdPersonMouseLook;
import com.jme.input.util.SyntheticButton;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Spatial;
import com.jme.scene.Text;
import com.jme.scene.shape.Box;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.PhysicsSpace;
import com.jmex.physics.PhysicsUpdateCallback;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.contact.ContactInfo;
import com.jmex.physics.material.Material;
import com.jmex.physics.util.SimplePhysicsGame;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.MidPointHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
/**
* This lesson shows a very simple example of modelling physics for a jump-and-run-like player character. It uses a box
* with an altered center of gravity. Moving the player is done with surface motion, jumping by directly applying
* forces.
* <p/>
* Important: this is, of course, not meant as <i>the</i> way to go! The actual physical representation that is chosen
* for characters in a game strongly depends on the abilities the character should have and the other effects you want
* to achieve. E.g. you could make a racing game with the approach shown here, but it will disregard many aspects you
* might want to have in a racing game...
* <p/>
* Especially not regarded here: character cannot be turned, rotation of the character is not restricted - it may turn
* when acting a while.
* @author Irrisor
*/
public class MyGame extends SimplePhysicsGame {
private ResourceFile dataFile;
private TerrainBlock tb;
private static final Vector3f ZERO = new Vector3f( 0, 0, 0 );
private StaticPhysicsNode floor;
private DynamicPhysicsNode player;
private boolean playerOnFloor = false;
private CharacterChaser chaser;
protected void simpleInitGame() {
try {
dataFile = new ResourceFile("data.fdb");
} catch (ZipException e) {
} catch (IOException e) {
}
try {
createFloor();
} catch (IOException e) {
e.printStackTrace();
}
// second we create a box - as we create multiple boxes this time the code moved into a separate method
player = createBox();
player.setName( "player" );
color( player, new ColorRGBA( 0, 0, 1, 1 ) );
player.getLocalTranslation().set( 8, 18, 0 );
player.setCenterOfMass( new Vector3f( 0, -0.5f, 0 ) );
final Material playerMaterial = new Material( "player material" );
player.setMaterial( playerMaterial );
buildChaseCamera();
input.removeAllActions();
input.addAction( new MoveAction( new Vector3f( -5, 0, 0 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_A, InputHandler.AXIS_NONE, false );
input.addAction( new MoveAction( new Vector3f( 5, 0, 0 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_D, InputHandler.AXIS_NONE, false );
input.addAction( new MoveAction( new Vector3f( 0, 0, 5 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_W, InputHandler.AXIS_NONE, false );
input.addAction( new MoveAction( new Vector3f( 0, 0, -5 ) ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_S, InputHandler.AXIS_NONE, false );
input.addAction( new InputAction() {
public void performAction( InputActionEvent evt ) {
if ( playerOnFloor && evt.getTriggerPressed() ) {
player.addForce( new Vector3f( 0, 500, 0 ) );
}
}
}, InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_SPACE, InputHandler.AXIS_NONE, false );
SyntheticButton playerCollisionEventHandler = player.getCollisionEventHandler();
input.addAction( new InputAction() {
public void performAction( InputActionEvent evt ) {
ContactInfo contactInfo = (ContactInfo) evt.getTriggerData();
if ( contactInfo.getNode1() == floor || contactInfo.getNode2() == floor ) {
playerOnFloor = true;
}
}
}, playerCollisionEventHandler, false );
// and a very simple callback to set the variable to false before each step
getPhysicsSpace().addToUpdateCallbacks( new PhysicsUpdateCallback() {
public void beforeStep( PhysicsSpace space, float time ) {
playerOnFloor = false;
}
public void afterStep( PhysicsSpace space, float time ) {
}
} );
// finally print a key-binding message
Text infoText = Text.createDefaultTextLabel( "key info", "[del] and [page down] to move, [home] to jump" );
infoText.getLocalTranslation().set( 0, 20, 0 );
statNode.attachChild( infoText );
}
private void buildChaseCamera() {
HashMap props = new HashMap();
props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "6");
props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "3");
props.put(ThirdPersonMouseLook.PROP_MAXASCENT, ""+45 * FastMath.DEG_TO_RAD);
props.put(ThirdPersonMouseLook.PROP_MOUSEBUTTON_FOR_LOOKING, "0");
props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(5, 0, 30 * FastMath.DEG_TO_RAD));
props.put(ChaseCamera.PROP_STAYBEHINDTARGET, true);
props.put(ChaseCamera.PROP_MAINTAINAZIMUTH, true);
System.out.println(ThirdPersonMouseLook.DEFAULT_MOUSEBUTTON_FOR_LOOKING);
chaser = new CharacterChaser(cam, player, props);
chaser.setMinDistance(20);
chaser.setMaxDistance(25);
chaser.setActionSpeed(.75f);
}
private void createFloor() throws IOException {
floor = getPhysicsSpace().createStaticNode();
rootNode.attachChild( floor );
//Add Terrain
MidPointHeightMap heightMap = new MidPointHeightMap(64, .5f);
Vector3f terrainScale = new Vector3f(20, 0.05f, 20);
tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale, heightMap.getHeightMap(), new Vector3f(0, 0, 0));
tb.setModelBound(new BoundingBox());
tb.updateModelBound();
ProceduralTextureGenerator pt = new ProceduralTextureGenerator(heightMap);
pt.addTexture(new ImageIcon(ImageIO.read(dataFile.getEntryByName("grassb.png").getStream())), -128, 0, 128);
pt.addTexture(new ImageIcon(ImageIO.read(dataFile.getEntryByName("dirt.jpg").getStream())), 0, 128, 255);
pt.addTexture(new ImageIcon(ImageIO.read(dataFile.getEntryByName("highest.jpg").getStream())), 128, 255,384);
pt.createTexture(32);
TextureState ts = display.getRenderer().createTextureState();
Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(), Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
ts.setTexture(t1, 0);
Texture t2 = TextureManager.loadTexture(ImageIO.read(dataFile.getEntryByName("Detail.jpg").getStream()),Texture.MinificationFilter.Trilinear,Texture.MagnificationFilter.Bilinear, true);
ts.setTexture(t2, 1);
t2.setWrap(Texture.WrapMode.Repeat);
t1.setApply(Texture.ApplyMode.Combine);
t1.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
t1.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
t1.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
t1.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
t1.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
t2.setApply(Texture.ApplyMode.Combine);
t2.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
t2.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
t2.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
tb.setRenderState(ts);
tb.setDetailTexture(1, 16);
tb.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
floor.attachChild(tb);
floor.generatePhysicsGeometry();
}
private DynamicPhysicsNode createBox() {
DynamicPhysicsNode dynamicNode = getPhysicsSpace().createDynamicNode();
rootNode.attachChild( dynamicNode );
final Box visualFallingBox = new Box( "falling box", new Vector3f(), 0.5f, 0.5f, 0.5f );
dynamicNode.attachChild( visualFallingBox );
dynamicNode.generatePhysicsGeometry();
return dynamicNode;
}
@Override
protected void simpleUpdate() {
chaser.update(tpf);
if(cam.getLocation().y < (tb.getHeight(cam.getLocation())+3)) {
cam.getLocation().y = tb.getHeight(cam.getLocation()) + 3;
cam.update();
}
cam.lookAt(player.getLocalTranslation(), Vector3f.UNIT_Y);
}
private class MoveAction extends InputAction {
private Vector3f direction;
public MoveAction( Vector3f direction ) {
this.direction = direction;
}
public void performAction( InputActionEvent evt ) {
if ( evt.getTriggerPressed() ) {
player.getMaterial().setSurfaceMotion( direction );
} else {
player.getMaterial().setSurfaceMotion( ZERO );
}
}
}
private void color( Spatial spatial, ColorRGBA color ) {
final MaterialState materialState = display.getRenderer().createMaterialState();
materialState.setDiffuse( color );
if ( color.a < 1 ) {
final BlendState blendState = display.getRenderer().createBlendState();
blendState.setEnabled( true );
blendState.setBlendEnabled( true );
blendState.setSourceFunction( BlendState.SourceFunction.SourceAlpha );
blendState.setDestinationFunction( BlendState.DestinationFunction.OneMinusSourceAlpha );
spatial.setRenderState( blendState );
spatial.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
}
spatial.setRenderState( materialState );
}
public static void main( String[] args ) {
Logger.getLogger( "" ).setLevel( Level.WARNING ); // to see the important stuff
new MyGame().start();
}
}
When I move my character around the camera does awkward stuff like moving forward andd backward ALOT. Is it because the TriMeshs of the terrain are bouncing with physics or what?