Hi all!
I’m new here and I don’t have much JMonkeyEngine experience, so please bear with me if I don’t understand anything.
In my project, I am importing a scene from blender and detecting collision to try to allow the character to wall jump. I am trying to do this by adding a CollisionListener to my class and attaching it to the BulletAppState. In my CollisionListener method, I am checking for collisions to see whether or not the character is on a wall, and if so to allow the character bounce off. The problem arises when I try to detect side collision. In my program, if I jump and walk sideways (or forward) into a wall while in the air, the CollisionListener does not register the collision. I have tried testing for this by disabling the jumping checks and just by printing out a line, but the problem still seems to appear.
Is this normal behavior? If so, how can I make the CollisionListener detect a sideways collision? If not, what am I doing wrong? Any help is much appreciated.
Code is attached below (Sorry I don’t know how to format it beyond 4 spaces and I don’t know how to see a live preview like with StackExchange):
package mygame;
<Insert imports here>
public class Main extends SimpleApplication implements ActionListener, PhysicsCollisionListener {
public static void main(String[] args) {
Main app = new Main();
app.start();
}
private Spatial scene;
private BulletAppState bullet;
private CharacterControl player;
private Node characterNode;
private Vector3f walkDirection = new Vector3f();
private Vector3f camDir = new Vector3f();
private Vector3f camLeft = new Vector3f();
private boolean left, right, up, down;
@Override
public void simpleInitApp() {
assetManager.registerLoader(BlenderLoader.class, "blend");
this.cam.setFrustumPerspective(70, 16f/9f, 0.01f, 100f);
scene = assetManager.loadModel("Scenes/Scene.blend");
scene.scale(10);
rootNode.attachChild(scene);
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
this.flyCam.setMoveSpeed(10);
bullet = new BulletAppState();
stateManager.attach(bullet);
setupInput();
setupCollision();
bullet.getPhysicsSpace().addCollisionListener(this);
setupLights();
setupEffects();
}
public void setupLights(){
/** A white, directional light source */
DirectionalLight sun = new DirectionalLight();
sun.setDirection((new Vector3f(-0.5f, -0.5f, -0.5f)).normalizeLocal());
sun.setColor(ColorRGBA.White);
rootNode.addLight(sun);
}
public void setupEffects(){
/* this shadow needs a directional light */
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
FXAAFilter fxaa = new FXAAFilter();
fpp.addFilter(fxaa);
viewPort.addProcessor(fpp);
}
public float capsuleHeight = 1.5f;
public void setupCollision(){
CollisionShape sceneCollisionShape = CollisionShapeFactory.createMeshShape(scene);
RigidBodyControl sceneControl = new RigidBodyControl(sceneCollisionShape, 0);
scene.addControl(sceneControl);
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.75f / 2f, capsuleHeight, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setGravity(new Vector3f(0,-30f,0));
characterNode = new Node();
characterNode.addControl(player);
characterNode.setName("player");
bullet.getPhysicsSpace().add(player);
bullet.getPhysicsSpace().add(sceneControl);
player.setPhysicsLocation(startingPosition);
}
private Vector3f startingPosition = new Vector3f(0, 10, 0);
public void setupInput(){
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(this, "Left");
inputManager.addListener(this, "Right");
inputManager.addListener(this, "Up");
inputManager.addListener(this, "Down");
inputManager.addListener(this, "Jump");
}
public boolean jump;
@Override
public void simpleUpdate(float tpf) {
if(player.getPhysicsLocation().y < -10)
player.setPhysicsLocation(startingPosition);
camDir.set(cam.getDirection()).multLocal(0.6f);
camLeft.set(cam.getLeft()).multLocal(0.4f);
walkDirection.set(0, 0, 0);
camDir.y = 0;
if (left) {
walkDirection.addLocal(camLeft);
}
if (right) {
walkDirection.addLocal(camLeft.negate());
}
if (up) {
walkDirection.addLocal(camDir);
}
if (down) {
walkDirection.addLocal(camDir.negate());
}
if(jump){
if (bottom || sides) {
/*if(sides){
System.out.println(reflect(walkDirection, collisionNormal));
player.setLinearVelocity(reflect(walkDirection, collisionNormal).mult(5));
}*/
System.out.println("jumping " + counter++ + " " + sides + " " + bottom);
//player.
player.jump(new Vector3f(0,10f,0));
}
}
player.setWalkDirection(walkDirection);
cam.setLocation(player.getPhysicsLocation());
sides = false;
bottom = false;
}
int counter;
public Vector3f reflect(Vector3f direction, Vector3f normal){
//r=d−2(d⋅n)n
return direction.subtract(normal.mult(2 * direction.dot(normal)));
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
@Override
public void onAction(String binding, boolean isPressed, float tpf) {
if (binding.equals("Left")) {
left = isPressed;
} else if (binding.equals("Right")) {
right = isPressed;
} else if (binding.equals("Up")) {
up = isPressed;
} else if (binding.equals("Down")) {
down = isPressed;
} else if (binding.equals("Jump")) {
jump = isPressed;
}
}
private boolean bottom, sides;
private Vector3f collisionNormal;
private int counter2;
@Override
public void collision(PhysicsCollisionEvent event) {
//Do not need to call super or anything like that
System.out.println("Objects Collide " + counter2++);
bottom = true;
/*if(event.getNodeA().getName().equals("player")){
collisionNormal = event.getNormalWorldOnB().negate();
collisionNormal.y = 0;
if(collisionNormal.angleBetween(Vector3f.UNIT_Y.negate()) > Math.toRadians(45)){
sides = true;
}else{
bottom = true;
}
}else if(event.getNodeB().getName().equals("player")){
collisionNormal = event.getNormalWorldOnB();
collisionNormal.y = 0;
if(collisionNormal.angleBetween(Vector3f.UNIT_Y.negate()) > Math.toRadians(45)){
sides = true;
}else{
bottom = true;
}
}*/
}
}