[Solved] Character (enemy) collision with player

I am trying to extend the Hello Collision tutorial for a small game.

I want to add 3 Oto objects and be able to shoot them.

I started with the tutorial code and added

[java] private Node createOto(float x, float y, float z)

{

CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);

CharacterControl oto_character = new CharacterControl(capsuleShape, 0.01f);

//load model

Node oto = (Node) assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);

//set position

oto.setLocalTranslation(x, y, z);

//set size

oto.setLocalScale(0.5f);

//enable shadows

oto.setShadowMode(ShadowMode.CastAndReceive);

oto.addControl(oto_character);

bulletAppState.getPhysicsSpace().add(oto_character);

return oto;

}[/java]

This places the Oto’s on the scene but know I have 2 problems

  1. The objects and not on the ground but rather float a bit above the ground.
  2. I can run trough the objects without colliding
  1. The capsule is too high
  2. Characters and characters do not collide, you can use a GhostControl to check for overlapping characters.
1 Like

normen thanks for the fast response.

For the first I checked with bulletAppState.getPhysicsSpace().enableDebug(assetManager); to finetune the capsule.

For the second I created a special Node (otoNode) and added a GhostControl for every oto.

During the simpleUpdate I looped trough all the nodes in otoNode to see if there was anything overlapping.

One other Issue I am having now (don’t know if I should start a new thread), is that when I add animation to my oto I get a error.

[java]

AnimControl control = oto.getControl(AnimControl.class);

control.addListener(this);

AnimChannel channel = control.createChannel();

channel.setAnim("stand");

[/java]

The given listener is already registed at this AnimControl

when I do control.clearListeners(); before the addListener it doesn't give the error and runs as expected

Well, so you add the listener some time before already.

which seems odd since I don’t do that explicitely



[java]private Node createOto(float x, float y, float z, String name) {

CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 2f, 1);

//CharacterControl oto_character = new CharacterControl(capsuleShape, 0.01f);

GhostControl oto_ghost = new GhostControl(capsuleShape);

//load model

Node oto = (Node) assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);

//set position

oto.setLocalTranslation(x, y, z);

//set size

oto.setLocalScale(0.5f);

//enable shadows

oto.setShadowMode(ShadowMode.CastAndReceive);

//oto.addControl(oto_character);

oto.addControl(oto_ghost);

bulletAppState.getPhysicsSpace().add(oto_ghost);

otoNode.attachChild(oto);

oto.setName(name);

AnimControl control = oto.getControl(AnimControl.class);

// control.clearListeners();

control.addListener(this);

AnimChannel channel = control.createChannel();

channel.setAnim(“stand”);

return oto;

}[/java]

Hi!

for example if you use a class like that:



public class HelloCollision extends SimpleApplication

implements ActionListener, AnimEventListener {





when you call the first

createOto(10, 4, 0, “test”);

you register this class “HelloCollision” as an event listener.



AnimControl control = oto.getControl(AnimControl.class);

control.addListener(this); //note the this statment



so, in the second call, you will try to register, again, the same listen class, and the code throws

an exception: “The given listener is already registed at this AnimControl”, because the class HelloCollision as already registered

as listener.



createOto(15, 4, 0, “test_1”);

that’s what I thought and tested



In the simpleUpdate method I added a call to checkCollision



[java]

private void checkCollision()

{

List<Spatial> otos = otoNode.getChildren();

for (Spatial oto : otos)

{

GhostControl otoGhost = oto.getControl(GhostControl.class);

if (otoGhost.getOverlappingCount() > 1) {

System.out.println(“Collision”);

List<PhysicsCollisionObject> objects = otoGhost.getOverlappingObjects();

System.out.println(oto.getName());

AnimControl control = oto.getControl(AnimControl.class);

control.getChannel(0).setAnim(“push”);

}

}

}[/java]



and I added

[java]public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {

System.out.println(“AnimCycleDone”);

if (animName.equals(“push”)) {

channel.setAnim(“stand”, 0.50f);

channel.setLoopMode(LoopMode.DontLoop);

channel.setSpeed(1f);

}

}[/java]



This would mean the push anim is triggered during a collision with the GhostControl (CapsuleCollisionShape) and after the first anim it would return to ‘stand’. However it does not trigger the “AnimCycleDone” and keeps on repeating the push anim.



When I explicitly perform control.clearListeners(); and control.addListener(this); It works as I expected it.

instead of using checkCollision use the PhysicsCollisionListener to detect collision’s



public class HelloCollision extends SimpleApplication

implements ActionListener, AnimEventListener, PhysicsCollisionListener {



@Override

public void collision(PhysicsCollisionEvent event) {

if (event.getObjectA() instanceof GhostControl) {

//System.out.println(“A-Object- collision detected”);

System.out.println(“A ->” + event.getNodeA().getName());



}



if (event.getObjectB() instanceof GhostControl) {

//System.out.println(“B-Object- collision detected”);

System.out.println(“B ->” + event.getNodeB().getName());

}

}

1 Like

thanks. I also added bulletAppState.getPhysicsSpace().addCollisionListener(this);

Still strange that animcycledone is not triggered in my custom checkCollision method but is triggered in the collision method.

drice said:
... I also added bulletAppState.getPhysicsSpace().addCollisionListener(this);


yes, I forgot in example code to put the call addCollisionListener ...

I think it is the following, but I'm not sure ...

when a collision happens an event is triggered, and that can be processed in
the event handler or not (if we don't set up the trigger), after that, the "colision
state" is cleared, so only by chance will be detected in the simple update ...

imo

hmmz but in the simpleUpdate we don’t check for the event. We check to see if there is an overlappingcount higher than 1. So I think this succesfully detects an overlap (in hindsight wrongfully for a collision since you already have an overlap).



I will do some more testing to see why the after the animation is done the animcycledone is not triggered. This has nothing to do with the collision since this only triggers the animation

see this

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:physics_listeners?s[]=physicscollisionevent