Collisions between player and objects

Hi,



I’m making sokoban-like game, and I’m stucked on collisions. So far I have scene (RigidBodyControl), player as CharacterControl and box (RigidBodyControl). I need to make player be able to hold box in hands and move it in same direction as player (attach box+rigidBody to playerNode). In same time (while player is walking) I need to check for all collisions between player+box against scene+allOtherObjects.

Which type of controls, collisions/physics should I use for player and boxes?



[java]package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.app.StatsAppState;

import com.jme3.asset.TextureKey;

import com.jme3.bounding.BoundingVolume;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.PhysicsSpace;

import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;

import com.jme3.bullet.control.CharacterControl;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.collision.CollisionResults;

import com.jme3.input.ChaseCamera;

import com.jme3.input.KeyInput;

import com.jme3.input.MouseInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.input.controls.TouchListener;

import com.jme3.input.controls.TouchTrigger;

import com.jme3.input.event.TouchEvent;

import com.jme3.light.AmbientLight;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Quaternion;

import com.jme3.math.Transform;

import com.jme3.math.Vector2f;

import com.jme3.math.Vector3f;

import com.jme3.renderer.queue.RenderQueue;

import com.jme3.scene.CameraNode;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;

import com.jme3.texture.Texture;



public class Main extends SimpleApplication implements ActionListener, TouchListener {



public Main(){

super(new StatsAppState());

}



private CharacterControl character;

private CameraNode camNode;

private Spatial sceneModel;

private CapsuleCollisionShape capsuleShape;

private RigidBodyControl rbc;

private Spatial model;

private Geometry reBoxg;

private Node playerNode;

private BulletAppState bulletAppState;

private ChaseCamera chaseCam;

private boolean left = false, right = false, up = false, down = false, picked = false, colide = false;

private Vector3f walkDirection = new Vector3f(0, 0, 0); // stop

private float airTime = 0;



public static void main(String[] args) {

Main app = new Main();

app.start();

}



@Override

public void simpleInitApp() {

//Set up physics

bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);

bulletAppState.getPhysicsSpace().enableDebug(assetManager);



// Load j3o SCENE

sceneModel = assetManager.loadModel(“Scenes/town/main.scene”);

sceneModel.setLocalTranslation(-20, 0, 20);

//sceneModel.setLocalScale(0.10f);

sceneModel.addControl(new RigidBodyControl(0));

rootNode.attachChild(sceneModel);

bulletAppState.getPhysicsSpace().addAll(sceneModel);





// Create player model

capsuleShape = new CapsuleCollisionShape(0.5f, 2f);

character = new CharacterControl(capsuleShape, 0.05f);

character.setJumpSpeed(20f);

model = assetManager.loadModel(“Models/robot/robot.j3o”);

model.scale(0.02f);



playerNode = new Node(“player”);

playerNode.setLocalTranslation(0, 10, 0);

playerNode.attachChild(model);

model.getLocalTranslation().subtractLocal(0, 2f, 0);

playerNode.addControl(character);

rootNode.attachChild(playerNode);

bulletAppState.getPhysicsSpace().add(character);





// Create box

Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

TextureKey key = new TextureKey(“Textures/Terrain/BrickWall/BrickWall.jpg”);

key.setGenerateMips(true);

Texture tex = assetManager.loadTexture(key);

mat.setTexture(“ColorMap”, tex);



Box brick = new Box(Vector3f.ZERO, 1, 1, 4);

brick.scaleTextureCoordinates(new Vector2f(1f, .5f));



reBoxg = new Geometry(“brick”, brick);

reBoxg.setMaterial(mat);

reBoxg.setLocalTranslation(new Vector3f(0, 1, 0));

//for geometry with sphere mesh the physics system automatically uses a sphere collision shape

rbc = new RigidBodyControl(0);

reBoxg.addControl(rbc);

reBoxg.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);

reBoxg.getControl(RigidBodyControl.class).setFriction(1.0f);

bulletAppState.getPhysicsSpace().add(reBoxg);

rootNode.attachChild(reBoxg);





// Add Light

AmbientLight light = new AmbientLight();

light.setColor(ColorRGBA.White.mult(2));

rootNode.addLight(light);



DirectionalLight dl = new DirectionalLight();

dl.setColor(ColorRGBA.White);

dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());

rootNode.addLight(dl);



// ********* CHASE CAMERA **********

chaseCam = new ChaseCamera(cam, model, inputManager);

chaseCam.setInvertVerticalAxis(true);

chaseCam.setDragToRotate(false);

// chaseCam.setMinDistance(0.001f);

// chaseCam.setMaxDistance(0.001f);

chaseCam.setDownRotateOnCloseViewOnly(false);

chaseCam.setDefaultVerticalRotation(0.0f);

chaseCam.setMaxVerticalRotation((float)Math.PI/4);

chaseCam.setMinVerticalRotation(-(float)Math.PI/4);

inputManager.setCursorVisible(false);

// ********* CHASE CAMERA **********



// configure mappings, eg. the WASD keys

inputManager.addMapping(“CharLeft”, new KeyTrigger(KeyInput.KEY_A));

inputManager.addMapping(“CharRight”, new KeyTrigger(KeyInput.KEY_D));

inputManager.addMapping(“CharForward”, new KeyTrigger(KeyInput.KEY_W));

inputManager.addMapping(“CharBackward”, new KeyTrigger(KeyInput.KEY_S));

inputManager.addMapping(“CharJump”, new KeyTrigger(KeyInput.KEY_SPACE));



inputManager.addListener(this, new String[]{“Touch”});

inputManager.addMapping(“Touch”, new TouchTrigger(0));



inputManager.addMapping(“Click”, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));

inputManager.addListener(this, “CharLeft”, “CharRight”);

inputManager.addListener(this, “CharForward”, “CharBackward”);

inputManager.addListener(this, “CharJump”, “Click”);



}



@Override

public void simpleUpdate(float tpf) {

CollisionResults results = new CollisionResults();

BoundingVolume bv = reBoxg.getWorldBound();

model.collideWith(bv, results);



Vector3f camDir = cam.getDirection().clone().multLocal(0.25f);

Vector3f camLeft = cam.getLeft().clone().multLocal(0.25f);

camDir.y = 0;

camLeft.y = 0;

walkDirection.set(0, 0, 0);



character.setViewDirection(camDir);



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(results.size() > 0){

colide = true;

}else{

colide = false;

}



character.setWalkDirection(walkDirection);

}



public void onAction(String binding, boolean pressed, float tpf) {



if (binding.equals(“CharLeft”)) {

if (pressed) {

left = true;

} else {

left = false;

}

} else if (binding.equals(“CharRight”)) {

if (pressed) {

right = true;

} else {

right = false;

}

} else if (binding.equals(“CharForward”)) {

if (pressed) {

up = true;

} else {

up = false;

}

} else if (binding.equals(“CharBackward”)) {

if (pressed) {

down = true;

} else {

down = false;

}

} else if (binding.equals(“CharJump”)) {

character.jump();

} else if (binding.equals(“Click”) && colide && !pressed){

if(picked){

picked = false;

rootNode.attachChild(reBoxg);

}else{

picked = true;

playerNode.attachChild(reBoxg);

}

}



}



public void onTouch(String name, TouchEvent evt, float tpf) {



}



}

[/java]

well the CharacterControl cannot exert a force, so you will have to use applyforce/impluse on the box yourself in a physics tick listener. I suggest applying the force in the opposite direction to the boxes surface normal which you collide with, this way the box shouldn’t move to its side