My 3rd person floats in the air and the camera should zoom out:
This is the program
package adventure;
import java.applet.Applet;
import com.jme3.math.Quaternion;
import com.jme3.math.FastMath;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.TextArea;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.jme3.material.RenderState.FaceCullMode;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.BlenderKey;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.effect.shapes.EmitterSphereShape;
import com.jme3.input.ChaseCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
import com.jme3.terrain.geomipmap.TerrainLodControl;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import com.jme3.util.SkyFactory;
public class MountainWorld extends SimpleApplication implements ActionListener,
PhysicsCollisionListener, AnimEventListener, Playable {
private static World world;
private static Person person;
private static Player dplayer;
private static TextArea textarea;
private BulletAppState bulletAppState;
private AnimChannel channel;
private AnimControl control;
// character
CharacterControl character;
Node model;
// temp vectors
Vector3f walkDirection = new Vector3f();
// terrain
TerrainQuad terrain;
RigidBodyControl terrainPhysicsNode;
// Materials
Material matRock;
Material matBullet;
// animation
AnimChannel animationChannel;
AnimChannel shootingChannel;
AnimControl animationControl;
float airTime = 0;
// camera
boolean left = false, right = false, up = false, down = false;
ChaseCamera chaseCam;
// bullet
Sphere bullet;
SphereCollisionShape bulletCollisionShape;
// explosion
ParticleEmitter effect;
// brick wall
Box brick;
float bLength = 0.8f;
float bWidth = 0.4f;
float bHeight = 0.4f;
FilterPostProcessor fpp;
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
AppSettings settings = new AppSettings(true);
settings.setWidth(850);
settings.setHeight(440);
MountainWorld canvasApplication = new MountainWorld();
canvasApplication.setSettings(settings);
canvasApplication.createCanvas(); // create canvas!
JmeCanvasContext ctx = (JmeCanvasContext) canvasApplication
.getContext();
ctx.setSystemListener(canvasApplication);
Dimension dim = new Dimension(640, 480);
ctx.getCanvas().setPreferredSize(dim);
JFrame window = new JFrame("Mountain World");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout()); // a panel
world = new DungeonWorld(canvasApplication);
person = new Person(world, "You", null);
dplayer = new Player(world, person);
Commands commands = new Commands(person);
textarea = new TextArea("", 10, 60,
TextArea.SCROLLBARS_VERTICAL_ONLY);
textarea.append("You are in a mountain. The trolls live here.\n");
textarea.setEditable(false);
panel.add("West", ctx.getCanvas());
panel.add("East", commands);
panel.add("South", textarea);
window.add(panel);
window.pack();
window.setVisible(true);
canvasApplication.startCanvas();
}
});
}
@Override
public void simpleInitApp() {
bulletAppState = new BulletAppState();
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
stateManager.attach(bulletAppState);
setupKeys();
prepareBullet();
prepareEffect();
createLight();
createSky();
createTerrain();
createWall();
createCharacters();
setupChaseCamera();
setupAnimationController();
setupFilter();
}
private void setupFilter() {
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
fpp.addFilter(bloom);
viewPort.addProcessor(fpp);
}
private PhysicsSpace getPhysicsSpace() {
return bulletAppState.getPhysicsSpace();
}
private void setupKeys() {
inputManager.addMapping("wireframe", new KeyTrigger(KeyInput.KEY_T));
inputManager.addListener(this, "wireframe");
inputManager.addMapping("CharLeft", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("CharRight", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("CharUp", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("CharDown", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("CharSpace",
new KeyTrigger(KeyInput.KEY_RETURN));
inputManager
.addMapping("CharShoot", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(this, "CharLeft");
inputManager.addListener(this, "CharRight");
inputManager.addListener(this, "CharUp");
inputManager.addListener(this, "CharDown");
inputManager.addListener(this, "CharSpace");
inputManager.addListener(this, "CharShoot");
}
private void createWall() {
float xOff = -144;
float zOff = -40;
float startpt = bLength / 4 - xOff;
float height = 6.1f;
brick = new Box(Vector3f.ZERO, bLength, bHeight, bWidth);
brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
for (int j = 0; j < 15; j++) {
for (int i = 0; i < 4; i++) {
Vector3f vt = new Vector3f(i * bLength * 2 + startpt, bHeight
+ height, zOff);
addBrick(vt);
}
startpt = -startpt;
height += 1.01f * bHeight;
}
}
private void addBrick(Vector3f ori) {
Geometry reBoxg = new Geometry("brick", brick);
reBoxg.setMaterial(matBullet);
reBoxg.setLocalTranslation(ori);
reBoxg.addControl(new RigidBodyControl(1.5f));
reBoxg.setShadowMode(ShadowMode.CastAndReceive);
this.rootNode.attachChild(reBoxg);
this.getPhysicsSpace().add(reBoxg);
}
private void prepareBullet() {
bullet = new Sphere(32, 32, 0.4f, true, false);
bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(0.4f);
matBullet = new Material(getAssetManager(),
"Common/MatDefs/Misc/Unshaded.j3md");
matBullet.setColor("Color", ColorRGBA.Green);
// matBullet.setColor("m_GlowColor", ColorRGBA.Green);
getPhysicsSpace().addCollisionListener(this);
}
private void prepareEffect() {
int COUNT_FACTOR = 1;
float COUNT_FACTOR_F = 1f;
effect = new ParticleEmitter("Flame", Type.Triangle, 32 * COUNT_FACTOR);
effect.setSelectRandomImage(true);
effect.setStartColor(new ColorRGBA(1f, 0.4f, 0.05f,
(float) (1f / COUNT_FACTOR_F)));
effect.setEndColor(new ColorRGBA(.4f, .22f, .12f, 0f));
effect.setStartSize(1.3f);
effect.setEndSize(2f);
effect.setShape(new EmitterSphereShape(Vector3f.ZERO, 1f));
effect.setParticlesPerSec(0);
effect.setGravity(0, -5, 0);
effect.setLowLife(.4f);
effect.setHighLife(.5f);
effect.setInitialVelocity(new Vector3f(0, 7, 0));
effect.setVelocityVariation(1f);
effect.setImagesX(2);
effect.setImagesY(2);
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("Texture",
assetManager.loadTexture("Effects/Explosion/flame.png"));
effect.setMaterial(mat);
// effect.setLocalScale(100);
rootNode.attachChild(effect);
}
private void createLight() {
Vector3f direction = new Vector3f(-0.1f, -0.7f, -1).normalizeLocal();
DirectionalLight dl = new DirectionalLight();
dl.setDirection(direction);
dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
rootNode.addLight(dl);
}
private void createSky() {
rootNode.attachChild(SkyFactory.createSky(assetManager,
"Textures/Sky/Bright/BrightSky.dds", false));
}
private void createTerrain() {
matRock = new Material(assetManager,
"Common/MatDefs/Terrain/TerrainLighting.j3md");
matRock.setBoolean("useTriPlanarMapping", false);
matRock.setBoolean("WardIso", true);
matRock.setTexture("AlphaMap",
assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
Texture heightMapImage = assetManager
.loadTexture("Textures/Terrain/splat/mountains512.png");
Texture grass = assetManager
.loadTexture("Textures/Terrain/splat/grass.jpg");
grass.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap", grass);
matRock.setFloat("DiffuseMap_0_scale", 64);
Texture dirt = assetManager
.loadTexture("Textures/Terrain/splat/dirt.jpg");
dirt.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_1", dirt);
matRock.setFloat("DiffuseMap_1_scale", 16);
Texture rock = assetManager
.loadTexture("Textures/Terrain/splat/road.jpg");
rock.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_2", rock);
matRock.setFloat("DiffuseMap_2_scale", 128);
Texture normalMap0 = assetManager
.loadTexture("Textures/Terrain/splat/grass_normal.jpg");
normalMap0.setWrap(WrapMode.Repeat);
Texture normalMap1 = assetManager
.loadTexture("Textures/Terrain/splat/dirt_normal.png");
normalMap1.setWrap(WrapMode.Repeat);
Texture normalMap2 = assetManager
.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
matRock.setTexture("NormalMap_1", normalMap2);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
try {
heightmap = new ImageBasedHeightMap(heightMapImage.getImage(),
0.25f);
heightmap.load();
} catch (Exception e) {
e.printStackTrace();
}
terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
List<Camera> cameras = new ArrayList<Camera>();
cameras.add(getCamera());
TerrainLodControl control = new TerrainLodControl(terrain, cameras);
terrain.addControl(control);
terrain.setMaterial(matRock);
terrain.setLocalScale(new Vector3f(2, 2, 2));
terrainPhysicsNode = new RigidBodyControl(
CollisionShapeFactory.createMeshShape(terrain), 0);
terrain.addControl(terrainPhysicsNode);
rootNode.attachChild(terrain);
getPhysicsSpace().add(terrainPhysicsNode);
}
private void createCharacters() {
CapsuleCollisionShape capsule = new CapsuleCollisionShape(3f, 4f);
character = new CharacterControl(capsule, 0.01f);
model = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
model.setLocalScale(0.15f);
//ninja.setViewDirection( new Vector3f( 1, 0, 1 ) );
//model.rotate(0.0f, -3.0f, 0.0f);
model.addControl(character);
character.setPhysicsLocation(new Vector3f(-140f, 9.9f, -9f));
character.setViewDirection(new Vector3f(1, 0, 0));
rootNode.attachChild(model);
getPhysicsSpace().add(character);
//BlenderKey blenderKey = new BlenderKey(
// "objects/creatures/alien/alien.mesh.xml");
//Node alien = (Node) assetManager.loadModel(blenderKey);
//alien.setLocalTranslation(new Vector3f(-145, 21, -10));
//rootNode.attachChild(alien);
BlenderKey blenderKey2 = new BlenderKey(
"objects/creatures/minotaur/minotaur.mesh.xml");
Spatial man = (Spatial) assetManager.loadModel(blenderKey2);
man.setLocalTranslation(new Vector3f(-140, 15, -10));
rootNode.attachChild(man);
}
private void setupChaseCamera() {
flyCam.setEnabled(false);
chaseCam = new ChaseCamera(cam, model, inputManager);
}
private void setupAnimationController() {
animationControl = model.getControl(AnimControl.class);
animationControl.addListener(this);
animationChannel = animationControl.createChannel();
//shootingChannel = animationControl.createChannel();
//shootingChannel.addBone(animationControl.getSkeleton().getBone(
// "uparm.right"));
//shootingChannel.addBone(animationControl.getSkeleton().getBone(
// "arm.right"));
//shootingChannel.addBone(animationControl.getSkeleton().getBone(
// "hand.right"));
}
@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.1f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.1f);
camDir.y = 0;
camLeft.y = 0;
walkDirection.set(0, 0, 0);
if (left) {
walkDirection.addLocal(camLeft);
}
if (right) {
walkDirection.addLocal(camLeft.negate());
}
if (up) {
walkDirection.addLocal(camDir);
}
if (down) {
walkDirection.addLocal(camDir.negate());
}
if (!character.onGround()) {
airTime = airTime + tpf;
} else {
airTime = 0;
}
if (walkDirection.length() == 0) {
if (!"Idle1".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("Idle1", 1f);
}
} else {
character.setViewDirection(walkDirection);
if (airTime > .3f) {
if (!"stand".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("stand");
}
} else if (!"Walk".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("Walk", 0.7f);
}
}
character.setWalkDirection(walkDirection);
}
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("CharLeft")) {
if (value) {
left = true;
} else {
left = false;
}
} else if (binding.equals("CharRight")) {
if (value) {
right = true;
} else {
right = false;
}
} else if (binding.equals("CharUp")) {
if (value) {
up = true;
} else {
up = false;
}
} else if (binding.equals("CharDown")) {
if (value) {
down = true;
} else {
down = false;
}
} else if (binding.equals("CharSpace")) {
character.jump();
} else if (binding.equals("CharShoot") && !value) {
bulletControl();
}
}
private void bulletControl() {
shootingChannel.setAnim("Dodge", 0.1f);
shootingChannel.setLoopMode(LoopMode.DontLoop);
Geometry bulletg = new Geometry("bullet", bullet);
bulletg.setMaterial(matBullet);
bulletg.setShadowMode(ShadowMode.CastAndReceive);
bulletg.setLocalTranslation(character.getPhysicsLocation().add(
cam.getDirection().mult(5)));
RigidBodyControl bulletControl = new BombControl(bulletCollisionShape,
1);
bulletControl.setCcdMotionThreshold(0.1f);
bulletControl.setLinearVelocity(cam.getDirection().mult(80));
bulletg.addControl(bulletControl);
rootNode.attachChild(bulletg);
getPhysicsSpace().add(bulletControl);
}
public void collision(PhysicsCollisionEvent event) {
if (event.getObjectA() instanceof BombControl) {
final Spatial node = event.getNodeA();
effect.killAllParticles();
effect.setLocalTranslation(node.getLocalTranslation());
effect.emitAllParticles();
} else if (event.getObjectB() instanceof BombControl) {
final Spatial node = event.getNodeB();
effect.killAllParticles();
effect.setLocalTranslation(node.getLocalTranslation());
effect.emitAllParticles();
}
}
public void onAnimCycleDone(AnimControl control, AnimChannel channel,
String animName) {
if (channel == shootingChannel) {
channel.setAnim("stand");
}
}
public void onAnimChange(AnimControl control, AnimChannel channel,
String animName) {
}
// Load an image from the net, making sure it has already been
// loaded when the method returns
public Image loadPicture(String imageName) {
return null;
}
// Load and play a sound from /usr/local/hacks/sounds/
public void playSound(String name) {
URL u = null;
try {
u = new URL("file:" + "/usr/local/hacks/sounds/" + name + ".au");
} catch (MalformedURLException e) {
}
AudioClip a = Applet.newAudioClip(u);
a.play();
}
}
I want the green person to stay on the ground but I can't seem to change the physicslocation to appropriate. Do you have any idea? I took this program and just switched the character from oto to ninja: http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/bullet/TestWalkingChar.java
Do you have any idea how I can make the camera zoom out so that the whole green person is displayed and change the location of the green person so that he is on the ground?
I've noticed that I can change the location of the main char with this
character.setPhysicsLocation(new Vector3f(-140f, 9.9f, -9f));
but when I put in lower y coordinates the main char drops through the ground and then floats way up in the sky like he ended up on the top of everything when he went through the ground. I could run the example with Oto perfectly, it's changing the main char to ninja that doesn't work for me.
Update
When using setlocaltranslation
instead of setphysicallocation
my main char gets located in the air:
Update 2
After scaling the main char:
model.scale(0.25f);
as suggested in the answer, the rendering is much better:
Update 2
After some more manipulation, it looks more like the way I want:
private void createCharacters() {
CapsuleCollisionShape capsule = new CapsuleCollisionShape(3f, 4f);
character = new CharacterControl(capsule, 0.01f);
model = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
model.setLocalScale(0.15f);
// ninja.setViewDirection( new Vector3f( 1, 0, 1 ) );
// model.rotate(0.0f, -3.0f, 0.0f);
float scale = 0.25f;
model.scale(scale, scale, scale);
model.addControl(character);
character.setPhysicsLocation(new Vector3f(-141f, 10.5f, -9f));
model.setShadowMode(ShadowMode.CastAndReceive);
// model.setLocalTranslation(0, 50, 0);
character.setViewDirection(new Vector3f(1, 0, 0));
rootNode.attachChild(model);
getPhysicsSpace().add(character);
// BlenderKey blenderKey = new BlenderKey(
// "objects/creatures/alien/alien.mesh.xml");
// Node alien = (Node) assetManager.loadModel(blenderKey);
// alien.setLocalTranslation(new Vector3f(-145, 21, -10));
// rootNode.attachChild(alien);
BlenderKey blenderKey2 = new BlenderKey("Models/Oto/Oto.mesh.xml");
Spatial man = (Spatial) assetManager.loadModel(blenderKey2);
man.setLocalTranslation(new Vector3f(-140, 10, -10));
// man.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(man);
}