[SOLVED] Problems with collision

Hello, my playerCBox won’t collide with my wallCol rigidBodyControl could someone please help me. Thanks

 /** Set up Physics */
    bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);
    //set up a wall?
   Box wall = new Box(1,10,1);
    cwall = new Geometry("Box",wall);
   cwall.setLocalTranslation(new Vector3f(2,0,2));
    cwall.setMaterial(mat);
    
    rootNode.attachChild(cwall);
    //collison with the floor;
    CollisionShape cs = CollisionShapeFactory.createMeshShape(scene);
    CollisionShape colWall = CollisionShapeFactory.createMeshShape(cwall);
    landscape = new RigidBodyControl(cs,0);
    wallCol = new RigidBodyControl(colWall, 0);
    CollisionShape playerBox = new BoxCollisionShape(new Vector3f(1,1,1));
    playerCBox = new CharacterControl(playerBox,1f);
    scene.addControl(landscape);
    cwall.addControl(wallCol);
            
    bulletAppState.getPhysicsSpace().add(playerCBox);
    bulletAppState.getPhysicsSpace().add(landscape);
    bulletAppState.getPhysicsSpace().add(wallCol);
    bulletAppState.setDebugEnabled(true);

Are you using the default fly-by-cam or a chase cam?

fly cam

I’m going to reproduce the code and do some testing…
I’ll find out how to attach physics to the flycam.

You’ve made a big assumption about how he is controlling his CharacterControl.

I don’t want to mess up on this, so do you have any more code besides what you posted?
It is easier to resolve problems the more information that is available.

Here’s all of my code

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.PlaneCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;

import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.math.ColorRGBA;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.scene.Spatial;

/**
 * This is the Main Class of your Game. You should only do initialization here.
 * Move your Logic into AppStates or Controls
 * @author normenhansen
 */
public class Main extends SimpleApplication {

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }
    
    public Geometry player;
    public Geometry cwall;
    private BulletAppState bulletAppState;//adds physics features like collsion
    private RigidBodyControl landscape; //makes landscape solid
    private RigidBodyControl wallCol;
    private boolean isRunning = true;
    CharacterControl playerCBox;
  
    @Override
    public void simpleInitApp(){
        Box b = new Box(1, 1, 1);
        player = new Geometry("Box", b);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setTexture("ColorMap", assetManager.loadTexture("Textures/grif.jpg"));
        player.setMaterial(mat);
        flyCam.setEnabled(false);
        initKeys();    
            /** A white ambient light source. */ 
        AmbientLight ambient = new AmbientLight();
        ambient.setColor(ColorRGBA.White);
        rootNode.addLight(ambient); 
        rootNode.attachChild(player);
        //terrain setup
        Spatial scene = assetManager.loadModel("Scenes/terrainCheck.j3o");
        rootNode.attachChild(scene);
    
    /** Set up Physics */
    bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);
    //set up a wall?
   Box wall = new Box(1,10,1);
    cwall = new Geometry("Box",wall);
   cwall.setLocalTranslation(new Vector3f(2,0,2));
    cwall.setMaterial(mat);
    
    rootNode.attachChild(cwall);
    //collison with the floor;
    CollisionShape cs = CollisionShapeFactory.createMeshShape(scene);
    CollisionShape colWall = CollisionShapeFactory.createMeshShape(cwall);
    landscape = new RigidBodyControl(cs,0);
    wallCol = new RigidBodyControl(colWall, 0);
    CollisionShape playerBox = new BoxCollisionShape(new Vector3f(1,1,1));
    playerCBox = new CharacterControl(playerBox,1f);
    scene.addControl(landscape);
    cwall.addControl(wallCol);
            
    bulletAppState.getPhysicsSpace().add(playerCBox);
    bulletAppState.getPhysicsSpace().add(landscape);
    bulletAppState.getPhysicsSpace().add(wallCol);
    bulletAppState.setDebugEnabled(true);
   
    
}

@Override
public void simpleUpdate(float tpf){
    //TODO: add update code
    Vector3f playerLocation = player.getLocalTranslation();
    cam.setLocation(new Vector3f(playerLocation.x,playerLocation.y,20f));
    playerCBox.setPhysicsLocation(new Vector3f(playerLocation.x,playerLocation.y,playerLocation.z));

    
}

private void initKeys() {
    // You can map one or several inputs to one named action
    inputManager.addMapping("Pause",  new KeyTrigger(KeyInput.KEY_P));
    inputManager.addMapping("Left",   new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping("Right",  new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping("FlyCam", new KeyTrigger(KeyInput.KEY_K));
    inputManager.addMapping("Up",   new KeyTrigger(KeyInput.KEY_W));
    inputManager.addMapping("Down",  new KeyTrigger(KeyInput.KEY_S));
    // Add the names to the action listener.
    inputManager.addListener(actionListener, "Pause","Left","Right","Pause","Up","Down","FlyCam");
}
private final ActionListener actionListener = new ActionListener() {
    /*
    Action Listener is a binary on off mapping
    Ex Movement(in this case) flipping doors pickup items 
    */
@Override
public void onAction(String name, boolean keyPressed, float tpf) {
    int speed = 1;
    if (name.equals("Pause") && !keyPressed) {
        isRunning = !isRunning;
    }
    if (name.equals("Left") && !keyPressed) {
        Vector3f v = player.getLocalTranslation();
        player.setLocalTranslation(v.x - speed, v.y, v.z);
        System.out.print(player.getLocalTranslation());//Prints out location of Player
    }
    if (name.equals("Right")&& !keyPressed) {
        Vector3f v = player.getLocalTranslation();
        player.setLocalTranslation(v.x + speed, v.y, v.z);
        System.out.print(player.getLocalTranslation()); //Prints out location of Player
    }
    if (name.equals("Up") && !keyPressed) {
        Vector3f v = player.getLocalTranslation();
        player.setLocalTranslation(v.x, v.y + speed, v.z);
        System.out.print(player.getLocalTranslation());//Prints out location of Player
    }
    if (name.equals("Down")&& !keyPressed) {
        Vector3f v = player.getLocalTranslation();
        player.setLocalTranslation(v.x, v.y - speed, v.z);
        System.out.print(player.getLocalTranslation()); //Prints out location of Player

    }
    if (name.equals("FlyCam")&& !keyPressed) {
        flyCam.setEnabled(true);

    }
}
};

private final AnalogListener analogListener = new AnalogListener() {
    @Override
    public void onAnalog(String name, float value, float tpf) {
        if (isRunning) {
            if (name.equals("Rotate")) {
                player.rotate(0, value * speed, 0);
            }
        } else {
            System.out.println("Press P to unpause.");
        }
    }
};

}

2 Likes

Havn’t said it yet, welcome to the community! :grinning:

It looks like your code is good to go.
I would try switching out this:

@Override
public void simpleUpdate(float tpf){
    //TODO: add update code
    Vector3f playerLocation = player.getLocalTranslation();
    cam.setLocation(new Vector3f(playerLocation.x,playerLocation.y,20f));
    playerCBox.setPhysicsLocation(new Vector3f(playerLocation.x,playerLocation.y,playerLocation.z));

    
}

For this:

@Override
public void simpleUpdate(float tpf){
    //TODO: add update code
    Vector3f playerLocation = player.getLocalTranslation();
    cam.setLocation(new Vector3f(playerLocation.x,playerLocation.y,20f));
    playerCBox.setPhysicsLocation(cam.getLocation());

    
}

If you are constantly teleporting your player then physics never comes into play… you will teleport them right through walls and so on.

That’s your issue.

2 Likes

How would I solve this then? I’m trying to create movement akin to roguelikes like Dwarf Fortress but still want walls that are impassable

Physics is for physical objects that move around with forces, etc…

If you just want a thing that jumps from cell to cell and doesn’t go into cells with something already there then that’s not a physics problem. That’s an array of tiles problem.

Could you point me to somewhere in the documentation where I can study this. I’m new to Jmonkey and want to get this movement down before I try other things.

1 Like

It’s not really a JME specific thing… just a game development thing.

Single stepping roguelike games generally just keep an array of tiles for the world. Tiles are walkable or they aren’t.

If you want your character to instead walk around freely in a physical space then you would use the approach that you are… but you wouldn’t teleport your character all over. You’d give them a direction and let them walk there.

https://wiki.jmonkeyengine.org/jme3/beginner/hello_collision.html

1 Like

one resource I found very approachable (which I refer to often) for any tile/grid based questions is Amit Patel’s page www.redblobgames.com. (especially Amit’s Thoughts on Grids for indexing, addressing, and grid maths)