I was following HelloCollision tutorial. I created my project and implemented it. It is a platform game and in the update loop I set the z-position to 0 so that the player doesn’t fall off. It works well, however I noticed that whenever I push both the left and right keys, the camera starts vibrating violently and the player loses its z-position and falls down. What should I do?
I wouldn’t suggest doing a 2d platform game using the same style as HelloCollision. I would suggest you move the character with the left/right keys and the camera just follows it:
[java]
public void simpleUpdate(float tpf) {
cam.setLocation( new Vector3f(spatial.getWorldTranslation().getX(), spatial.getWorldTranslation().getY(), 10);
cam.lookAt(new Vector3f(spatial.getWorldTranslation()), new Vector3f(0,1,0));
spatial.getLocalTranslation().multLocal(new Vector3f(1,1,0)); //keep him on Z axis
}[/java]
Will try that tonight, thanks I think the problem was that I tried converting a first-person into a third-person.
Now the character doesn’t collide with the walls I made. Beforehand, the character used to stop, but now I can walk right through vertical walls. Any help?
When I tried reducing the speed, the character stops walking through walls, but the speed has to be very low. The following is the code I am using to move to the right. Variable pos is the position of the player:
[java]player.setPhysicsLocation(new Vector3f(pos.x+0.5f, pos.y, 0));[/java]
you should be multiplying your increment value (0.5f), by the frame independent value, think its called “float value” in the docs. Dunno if it helps tho, but maybe
@wezrule, couldn’t find it. The following is my program. Would appreciate any help because I don’t know what to do
[java]package Platform;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
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.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
public class Main extends SimpleApplication
implements ActionListener {
private Geometry green;
private BulletAppState bulletAppState;
private RigidBodyControl f;
private CharacterControl player;
private boolean bind = false;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
public static void main(String[] args) {
AppSettings settings=new AppSettings(true);
settings.put(“Width”, 640);
settings.put(“Height”, 480);
settings.put(“Title”, “Platform”);
settings.put(“VSync”, true);
settings.put(“Samples”, 4);
Main app = new Main();
app.setSettings(settings);
app.setShowSettings(false);
app.start();
}
public void simpleInitApp(){
viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f));
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
flyCam.setEnabled(false);
setUpKeys();
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1f, 0f, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(2, 10, 0));
Box box2 = new Box( new Vector3f(0,0,0), 1,1,1);
green = new Geometry(“Box”, box2);
Material mat2 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat2.setColor(“Color”, ColorRGBA.Green);
green.setMaterial(assetManager.loadMaterial( “Materials/Ground.j3m”));
rootNode.attachChild(green);
bulletAppState.getPhysicsSpace().add(player);
SimpleLevel l = new SimpleLevel();
int block;
block = l.blocknumber;
for (int i = 1; i < block; i++){
l.geom.setMaterial(assetManager.loadMaterial( “Materials/Ground.j3m”));
CollisionShape sceneShape2 = CollisionShapeFactory.createMeshShape(l.geom);
f = new RigidBodyControl(sceneShape2, 0);
l.geom.addControl(f);
System.out.println(l.geom.getLocalTranslation());
rootNode.attachChild(l.geom);
bulletAppState.getPhysicsSpace().add(f);
bulletAppState.getPhysicsSpace().add(player);
}
DirectionalLight light = new DirectionalLight();
light.setDirection( new Vector3f( -1f, -1f, -1f));
light.setColor(ColorRGBA.White.mult(0.5f));
rootNode.addLight( light );
AmbientLight amb = new AmbientLight();
amb.setColor(ColorRGBA.White.mult(1f));
rootNode.addLight(amb);
}
private void setUpKeys() {
inputManager.addMapping(“Lefts”, new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping(“Rights”, new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping(“Jumps”, new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(this, “Lefts”);
inputManager.addListener(this, “Rights”);
inputManager.addListener(this, “Jumps”);
}
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals(“Lefts”)) {
left = value;
} else if (binding.equals(“Rights”)) {
right = value;
} else if (binding.equals(“Jumps”)){
player.jump();
}
}
@Override
public void simpleUpdate(float tpf) {
Vector3f pos = new Vector3f(player.getPhysicsLocation());
ChaseCamera bluechase = new ChaseCamera(cam, green);
bluechase.setDefaultHorizontalRotation(1.565f);
bluechase.setLookAtOffset(new Vector3f(0, 0, 0));
bluechase.setChasingSensitivity(0f);
green.addControl(bluechase);
green.setLocalTranslation(player.getPhysicsLocation());
float v = 0.5f;
if (left) {
player.setPhysicsLocation(new Vector3f(pos.x-v, pos.y, 0));
}
if (right) {
player.setPhysicsLocation(new Vector3f(pos.x+v, pos.y, 0));
}
}
}[/java]
do 0.5f * tpf
- The speed is way too slow.
- If I increase it, the same thing happens, the character walks through walls.
k well from quickly glancing through your code, your capsuleCollisionShape doesn’t have a height? and do bulletAppState.getPhysicsSpace().enableDebug(true); so you can see your collisionshapes
hmm… There is no collision shape visible on the screen Note that the player doesn’t fall through ground.
Ok on further inspection i find even more things: You don’t attach the CharacterControl (player) to a spatial, and also you call bulletAppState.getPhysicsSpace().add(player); for every block added, it’s only need once. You need to look through your code more carefully, there’s a lot of things which can attribute to the given behaviour.
player isn’t a spatial. I don’t use spatials in this one, only Geometries (box), Also, I only callulletAppState.getPhysicsSpace().add(player); once…
Will continue working on it tomorrow. If you find the problem, please tell me.
ok you don’t need to attatch the characterControl to a spatial, but:
memonick said:
I don't use spatials in this one, only Geometries (box),
A geometry is a spatial
memonick said:
Also, I only callulletAppState.getPhysicsSpace().add(player); once...
oh rly?
for (int i = 1; i < block; i++){
l.geom.setMaterial(assetManager.loadMaterial( "Materials/Ground.j3m"));
CollisionShape sceneShape2 = CollisionShapeFactory.createMeshShape(l.geom);
f = new RigidBodyControl(sceneShape2, 0);
l.geom.addControl(f);
System.out.println(l.geom.getLocalTranslation());
rootNode.attachChild(l.geom);
bulletAppState.getPhysicsSpace().add(f);
bulletAppState.getPhysicsSpace().add(player);
}
@wezrule, sorry, I didn’t realize I was showing you an old piece of code. I updated it. Sorry.
What do I need to change from the below code? I really don’t understand what you mean about not attaching spatials to character controls. The geometries (except green) are the boxes I want to add as ground.
[java]
package Platform;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
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.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
public class Main extends SimpleApplication
implements ActionListener {
private Geometry green;
private BulletAppState bulletAppState;
private RigidBodyControl f;
private CharacterControl player;
private boolean bind = false;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
public static void main(String[] args) {
AppSettings settings=new AppSettings(true);
settings.put(“Width”, 640);
settings.put(“Height”, 480);
settings.put(“Title”, “Platform”);
settings.put(“VSync”, true);
settings.put(“Samples”, 4);
Main app = new Main();
app.setSettings(settings);
app.setShowSettings(false);
app.start();
}
public void simpleInitApp(){
viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f));
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
flyCam.setEnabled(false);
setUpKeys();
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1f, 1f, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(2, 10, 0));
Box box2 = new Box( new Vector3f(0,0,0), 1f,1f,1f);
green = new Geometry(“Box”, box2);
Material mat2 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat2.setColor(“Color”, ColorRGBA.Green);
green.setMaterial(assetManager.loadMaterial( “Materials/Ground.j3m”));
rootNode.attachChild(green);
bulletAppState.getPhysicsSpace().add(player);
bulletAppState.getPhysicsSpace().enableDebug(assetManager);
SimpleLevel l = new SimpleLevel();
int block;
block = l.blocknumber;
for (int i = 1; i < block; i++){
l.geom.setMaterial(assetManager.loadMaterial( “Materials/Ground.j3m”));
CollisionShape sceneShape2 = CollisionShapeFactory.createMeshShape(l.geom);
f = new RigidBodyControl(sceneShape2, 0);
l.geom.addControl(f);
System.out.println(l.geom.getLocalTranslation());
rootNode.attachChild(l.geom);
bulletAppState.getPhysicsSpace().add(f);
}
DirectionalLight light = new DirectionalLight();
light.setDirection(new Vector3f( -1f, -1f, -1f));
light.setColor(ColorRGBA.White.mult(0.5f));
rootNode.addLight( light );
AmbientLight amb = new AmbientLight();
amb.setColor(ColorRGBA.White.mult(1f));
rootNode.addLight(amb);
}
private void setUpKeys() {
inputManager.addMapping(“Lefts”, new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping(“Rights”, new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping(“Jumps”, new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(this, “Lefts”);
inputManager.addListener(this, “Rights”);
inputManager.addListener(this, “Jumps”);
}
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals(“Lefts”)) {
left = value;
} else if (binding.equals(“Rights”)) {
right = value;
} else if (binding.equals(“Jumps”)){
player.jump();
}
}
@Override
public void simpleUpdate(float tpf) {
Vector3f pos = new Vector3f(player.getPhysicsLocation());
ChaseCamera bluechase = new ChaseCamera(cam, green);
bluechase.setDefaultHorizontalRotation(1.565f);
bluechase.setLookAtOffset(new Vector3f(0, 0, 0));
bluechase.setChasingSensitivity(0f);
green.addControl(bluechase);
green.setLocalTranslation(player.getPhysicsLocation());
float v = 0.5f;
if (left) {
player.setPhysicsLocation(new Vector3f(pos.x-v, pos.y, 0));
}
if (right) {
player.setPhysicsLocation(new Vector3f(pos.x+v, pos.y, 0));
}
}
}[/java]
EDIT: Increased the capsuleshape’s values. Now the player doesn’t pass through geometries, but the camera vibrates a lot when colliding.
Anyone please?
Dude!!! You didn’t even wait two hours for an answer!! Bump more aggressively like this and I close your thread.
Sorry, but I’m kinda desperate. It’s like seeing all my work getting undone I’ll stop bumping, don’t worry.
I made this in the first few days of coming to JME, and knowing nothing about making games. Its just a simple “2d” scene with a character (with a big collision shape, i might add), and it’s probably got a lot of stuff you don’t want like a control for an enemy, but ill let you figure that out. It doesn’t make use of a chase cam, just the standard cam which i suggested to you early on that you should use. See if you get the same “shaking” you got previously. Also you’ll need the test-data.jar file in your class path:
Main.java
[java]package mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.Node;
import com.jme3.light.AmbientLight;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.math.FastMath;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.KeyInput;
import com.jme3.scene.shape.Box;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.util.SkyFactory;
/**
- test
*
-
@author normenhansen
/
public class Main extends SimpleApplication implements ActionListener, PhysicsCollisionListener {
public BulletAppState bulletAppState;
private Node model;
private CharacterControl characterControl;
private boolean left = false, right = false;
private float increaseAmount = 1f;
private Vector3f newLoc;
public static void main(String[] args) {
Main app = new Main();
app.start();
}
@Override
public void simpleInitApp() {
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
createWorld();
createCharacter();
createEnemy();
setUpLights();
setupCamera();
setupKeys();
bulletAppState.getPhysicsSpace().enableDebug(assetManager);
bulletAppState.getPhysicsSpace().addCollisionListener(this);
rootNode.attachChild(SkyFactory.createSky(
assetManager, "Textures/Sky/Bright/BrightSky.dds", false));
}
@Override
public void collision(PhysicsCollisionEvent event) {
if (event.getNodeA() != null) {
RigidBodyControl r = event.getNodeA().getControl(RigidBodyControl.class);
if (r != null) {
r.setPhysicsLocation(r.getPhysicsLocation().mult(new Vector3f(1, 1, 0)));
}
}
if (event.getNodeB() != null) {
RigidBodyControl r = event.getNodeB().getControl(RigidBodyControl.class);
if (r != null) {
r.setPhysicsLocation(r.getPhysicsLocation().mult(new Vector3f(1, 1, 0)));
}
}
}
@Override
public void simpleUpdate(float tpf) {
//move the character in response to the keys pressed
newLoc = characterControl.getPhysicsLocation();
if (left) {
newLoc.addLocal(-increaseAmount * tpf, 0, 0);
}
if (right) {
newLoc.addLocal(increaseAmount * tpf, 0, 0);
}
newLoc.multLocal(new Vector3f(1, 1, 0));
characterControl.setPhysicsLocation(newLoc);
//move camera to this location
cam.setLocation(new Vector3f(characterControl.getPhysicsLocation().getX(), characterControl.getPhysicsLocation().getY(), 10));
cam.lookAt(new Vector3f(characterControl.getPhysicsLocation()), new Vector3f(0, 1, 0));
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
public void createWorld() {
Spatial s = assetManager.loadModel("Scenes/MainLevel.obj");
Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
m.setColor("Color", ColorRGBA.Red);
s.setMaterial(m);
s.rotate(0, FastMath.DEG_TO_RAD * -90, 0);
s.addControl(new RigidBodyControl(0));
rootNode.attachChild(s);
bulletAppState.getPhysicsSpace().add(s);
}
public void createCharacter() {
CapsuleCollisionShape shape = new CapsuleCollisionShape(0.5f, 0.5f);
characterControl = new CharacterControl(shape, 1);
characterControl.setGravity(1f);
model = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
model.setName("Character");
model.setLocalScale(0.01f);
model.addControl(characterControl);
characterControl.setPhysicsLocation(new Vector3f(-1, 2, 0));
rootNode.attachChild(model);
bulletAppState.getPhysicsSpace().add(characterControl);
}
public void createEnemy() {
Box b = new Box(Vector3f.ZERO, 0.1f, 0.1f, 0.1f);
Spatial boxEnemy = new Geometry("Enemy", b);
boxEnemy.setName("Enemy");
boxEnemy.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"));
boxEnemy.setLocalTranslation(0.15f, 1, 0);
boxEnemy.addControl(new RigidBodyControl(1));
boxEnemy.addControl(new SideToSideControl(this));
rootNode.attachChild(boxEnemy);
bulletAppState.getPhysicsSpace().add(boxEnemy);
}
public void setUpLights() {
AmbientLight ambient = new AmbientLight();
ambient.setColor(ColorRGBA.White);
rootNode.addLight(ambient);
}
private void setupCamera() {
flyCam.setEnabled(false);
//make the camera initially pointed at the character
cam.setLocation(new Vector3f(characterControl.getPhysicsLocation().getX(), characterControl.getPhysicsLocation().getY(), 10));
cam.lookAt(new Vector3f(characterControl.getPhysicsLocation()), new Vector3f(0, 1, 0));
}
private void setupKeys() {
inputManager.addMapping("left", new KeyTrigger(KeyInput.KEY_LEFT));
inputManager.addMapping("right", new KeyTrigger(KeyInput.KEY_RIGHT));
inputManager.addListener(this, "left", "right");
}
@Override
public void onAction(String name, boolean keypressed, float tpf) {
if (name.equals("left")) {
if (keypressed) {
left = true;
} else {
left = false;
}
} else if (name.equals("right")) {
if (keypressed) {
right = true;
} else {
right = false;
}
}
}
}
[/java]
SideToSideControl.java
[java]package mygame;
import com.jme3.math.Vector3f;
import com.jme3.scene.control.Control;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import java.io.IOException;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.export.InputCapsule;
import com.jme3.bullet.control.PhysicsControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
public class SideToSideControl implements Control, PhysicsCollisionListener {
protected Spatial spatial;
protected boolean enabled = true;
private Vector3f translation;
private SimpleApplication myApp;
public SideToSideControl(SimpleApplication app) {
myApp = app;
((Main)myApp).bulletAppState.getPhysicsSpace().addCollisionListener(this);
}
@Override
public void update(float tpf) {
if (enabled && spatial != null) {
// …
// Write custom code to control the spatial here!
moveSpatial(tpf);
}
}
@Override
public void collision(PhysicsCollisionEvent event) {
//get coordinates to stay within
if(event.getNodeA().getName().equals("Character") && event.getNodeB().getName().equals("Enemy")){
System.out.println("hit");
}
// else if(event.getNodeB().getName().equals("Character")){
else if(event.getNodeB().getName().equals("Character") && event.getNodeA().getName().equals("Enemy")){
System.out.println("hit");
}
}
public void moveSpatial(float tpf){
spatial.getControl(RigidBodyControl.class).setPhysicsLocation(spatial.getControl(RigidBodyControl.class).getPhysicsLocation().subtract(new Vector3f(tpf0.5f,0,0)));
}
@Override
public void render(RenderManager rm, ViewPort vp) {
// optional, e.g. to display a debug shape
}
@Override
public Control cloneForSpatial(Spatial spatial) {
SideToSideControl control = new SideToSideControl(myApp);
// …
spatial.addControl(control);
return control;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
// …
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public void write(JmeExporter ex) throws IOException {
//super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
oc.write(enabled, "enabled", true);
oc.write(spatial, "spatial", null);
// write custom variables …
}
@Override
public void read(JmeImporter im) throws IOException {
// super.read(im);
InputCapsule ic = im.getCapsule(this);
enabled = ic.readBoolean("enabled", true);
spatial = (Spatial) ic.readSavable("spatial", null);
// read custom variables …
}
@Override
public void setSpatial(Spatial spatial) {
// super.read(im);
this.spatial = spatial;
translation = spatial.getLocalTranslation();
}
}
[/java]
Edit: ok sorry you also need the scene file.
http://www.mediafire.com/?a8u38grb778ekl3 - MainLevel.obj
http://www.mediafire.com/?gb4a99xp0u1j5ss - MainLevel.mtl