Collision detection problem (I know you guys beat this dead hores, but still)

I’ve looked up, what I believe to be every tutorial, discussion or document on the subject and I’m a tad confused. (Probably because I’m still very new to JMonkey).

I have a very simple game. The object is to shoot a box, if you hit the box, it tells you you hit the box. This requires the collision detection, which I can’t seem to get working.

I have the following:

[java]
public void simpleInitApp() {
Box box = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry objective = new Geometry(“Objective”, box);
Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat.setTexture(“ColorMap”, tex2);
mat.setColor(“Color”, ColorRGBA.Blue);
objective.setMaterial(mat);

com.jme3.bullet.collision.shapes.CollisionShape objectiveBoxShape = 
        CollisionShapeFactory.createDynamicMeshShape(objective);
GhostControl objectiveGhost = new GhostControl(objectiveBoxShape);
objective.addControl(objectiveGhost); 
bulletAppState.getPhysicsSpace().add(objectiveGhost);
rootNode.attachChild(objective);

...
...

}

public void makeBullet() { //called when they click the mouse button (came from the tutorial)
com.jme3.bullet.collision.shapes.CollisionShape bulletShape =
CollisionShapeFactory.createDynamicMeshShape(bullet);
GhostControl bulletGhost = new GhostControl(bulletShape);
bullet.addControl(bulletGhost);
bulletAppState.getPhysicsSpace().add(bulletGhost);


}

public void collision(PhysicsCollisionEvent event) {
System.out.println(“pass1”);
if (event.getNodeA().getName().equals(“Bullet”) ||
event.getNodeB().getName().equals(“Bullet”)) {
System.out.println(“pass2”);
if (event.getNodeA().getName().equals(“Objective”) ||
event.getNodeB().getName().equals(“Objective”)) {
fpsText.setText(“You hit the box!”);
System.out.println(“pass3”);
}
}
}
[/java]

The code above is a starting point I got from all the tutorials and such on the site, but I’m not sure how the collision() method works. How do I find an “even” to call the collision method with? I would think that events would happen when collisions occur but I don’t know what to do from this point to actually get the collision() method to do what its supposed to do. I’m missing the key ingredient here.

Any help would be appreciated, thanks!

Are you just randomly creating a collision() method and hoping it gets called? Or are you implementing the proper interface? http://hub.jmonkeyengine.org/javadoc/com/jme3/bullet/collision/PhysicsCollisionListener.html

…and then registering the listener somewhere?

This kind of thing seems to be covered here: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:physics_listeners
…near the end, I guess.

Haha, oh my. Well no it’s not just a completely random collision() method, its inside a MyCustomControl class. While it’s not totally random, however, it isn’t ever called. I don’t know how to call that method, because I don’t know where to get an ‘event’ and it requires an event as a parameter in order to pull out event objects names etc.

I registered the MyCustomControl listener in the SimpleInitApp() method, but I don’t know where I should be calling the collision() or how I get an ‘event’ to pass to it.

Collision events don’t exist until a collision happens, but I don’t know where they are stored or how they can be retrieved once they start happening. The link you provided is great, but maybe I’ve been staring at it too long. The MyCustomControl class has a method for handling an event collision() but there’s no method to get or return an ‘event’ so how is it really ‘listening’ to anything? What method should I be adding to actually retrieve an event?

I think I’m just not sure:

  1. Where to register the listener
  2. Where/how to ‘get’ an event
  3. (pretty sure) you call the collision(PhysicsCollisionEvent event) method inside the SimpleInitUpdate() method, passing the event and checking for the right objects.

That method is called for you if you register the listener properly. It’s at the end of the link I posted. I know nothing about Bullet integration and found it in five minutes… just read that document all the way through and look at the end where it is adding the listener.

Well, I see that you have to register the listener to the physics space, but that isn’t helping either. Let me be more clear:

I have the following:

[java]
public void simpleInitApp() {
Box box = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry objective = new Geometry(“Objective”, box);
Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat.setTexture(“ColorMap”, tex2);
mat.setColor(“Color”, ColorRGBA.Blue);
objective.setMaterial(mat);

com.jme3.bullet.collision.shapes.CollisionShape objectiveBoxShape =
        CollisionShapeFactory.createDynamicMeshShape(objective);
GhostControl objectiveGhost = new GhostControl(objectiveBoxShape);
objective.addControl(objectiveGhost);
bulletAppState.getPhysicsSpace().add(objectiveGhost);
rootNode.attachChild(objective);

ShootBoxPhysicsControl physicsControl = new ShootBoxPhysicsControl();  // returns null pointer exception, crashes game
bulletAppState.getPhysicsSpace().addCollisionListener(physicsControl);

…
…

}

public void makeBullet() { //called when they click the mouse button (came from the tutorial)
com.jme3.bullet.collision.shapes.CollisionShape bulletShape =
CollisionShapeFactory.createDynamicMeshShape(bullet);
GhostControl bulletGhost = new GhostControl(bulletShape);
bullet.addControl(bulletGhost);
bulletAppState.getPhysicsSpace().add(bulletGhost);


}

[/java]

And I have the following physics control class, which came straight out of that physics listener document you linked:

[java]
public class ShootBoxPhysicsControl extends RigidBodyControl
implements PhysicsCollisionListener {
// I’m not sure if i should be passing the main bulletAppState or make a new one, I could trouble shoot this.
BulletAppState bulletAppState; // this wasn’t here in the example, had to add it for the constructor to work.
public ShootBoxPhysicsControl() {
bulletAppState.getPhysicsSpace().addCollisionListener(this);
}

public void collision(PhysicsCollisionEvent event) {
if ( event.getNodeA().getName().equals("player") ) {
    final Node node = (Node) event.getNodeA();
    /** ... do something with the node ... */
}   else if ( event.getNodeB().getName().equals("player") ) {
    final Node node = (Node) event.getNodeB();
    /** ... do something with the node ... */
    }
}

}
[/java]

Step one debugging:
Put a System.out.println() after this line:
public void collision(PhysicsCollisionEvent event) {

…see if your listener is even getting called… then see what it’s being called with… then profit.

Nothing, it’s not getting called because the entire game won’t even run. It crashes when I create the PhysicsCollisionListener.

@leigero said: Nothing, it's not getting called because the entire game won't even run. It crashes when I create the PhysicsCollisionListener.

Crash can be interpretted many ways:
-Machine explodes
-OS crashes to blue screen (or kernel panic, or whatever)
-App crashes to desktop with no stack trace
-App crashes with exception

If the last one then the exception stack trace would be useful.

My guess is that you are getting a NullPointerException since your code shows that you are new to Java and Object Oriented programming and perhaps don’t know how to pass references around… or I’m seeing code that’s not real.

I stated in my updated post with comments that the line;

ShootBoxPhysicsControl physicsControl = new ShootBoxPhysicsControl():

was causing a nullPointerException.

What reference should I be passing around? I mentioned all of this in my code comments. If I should be passing a BulletAppState to the control, then that’s not a big deal, I mentioned that in my comments as well.

After doing this, it sort of works. I at least got collision events… the nullPointerExceptions appear to be happening after the ‘character’ hits the ground. When starting the camera is just slightly above the terrain.

I have no ghost objects for the earth or the character, so why would they even be caling the collision() method? The document states that the ghost controls are what check for collision events and there are only two objects in the game with a GhostControl

What do you expect this “value you’ve never set to anything” to be?

Hint: this is where your NullPointerException is coming from.

Yeah, I see this. Should I make a separate BulletAppState for the ghost controls and handle them separate from all of the other objects in the scene?

@leigero said: Yeah, I see this. Should I make a separate BulletAppState for the ghost controls and handle them separate from all of the other objects in the scene?

No, you should pass a reference on the constructor.

I apologize for wading into this thread. Over a long career, I’ve had to teach many people programming basics and I just don’t have any patience for it anymore. Hopefully someone else will pick up the ball to help you learn Java and OOP enough to get your problem solved. You are learning to swim by jumping into the deep part of the ocean… which is your choice and can be fun… but I don’t have the stomach for it anymore. :slight_smile:

I know how to code in Java. The problem isn’t my knowledge of Java… its my knowledge of your extensive JMonkey library, of which I know nothing about. The issues come when the tutorials don’t work and with little knowledge of what the library does, and a lack of working examples, it makes learning it difficult.

I think you’ve been considerably patient thus far and I do appreciate it, but being rude is going to make people leave for another game engine. You haven’t read my posts thoroughly and are picking apart things I’ve already mentioned in my previous posts.

I passed the BulletAppState into the constructor… that didn’t fix the problem, I mentioned that probably 20 minutes ago before you suggested I don’t even know how to pass objects. The problem is that even passing the BulletAppState into the CustomControl class doesn’t matter. The ghostControls are supposedly the only things creating collision events (according to your documents) and yet they are not. I’m getting null pointer exceptions when the character comes in contact with the ground which doesn’t add up to me.

Perhaps if there were a working example of an object hitting another object I would just disassemble that before getting berated on the forums. I’m not here for my enjoyment.

Well, when I see you saying you get a NullPointerException and it’s clear you are accessing a null value because you haven’t passed a reference on the constructor… then I make assumptions. I apologize.

Edit: but note, telling someone they are new to Java is not an insult on its own. There is a little bit of language-based casting about that you do that indicates inexperience. It may just be the way you solve problems.

I’m certainly not a pro. I’m not a noob either. I’m a quick learner and I love code, but I definitely know all the year one basics. The (Node) casting? The JMonkey IDE refused to accept what was posted in the document and the event nodes had to be cast into (Nodes) unless you just mean in general.

Right now I’m making a Franken-style game composed of a bunch of tutorials so most of this code isn’t even mine. It came from the tutorials and documents like that PhysicsCollisionListener page etc. I think I pretty well understand most of what I have thus far, but I’m trying to get:

1: A world, that I made, with a character in it (CHECK)
2: A character that shoots objects that I made (CHECK)
3. A print statement when the object I shoot collides with a box (FAIL)

And right now I’m getting NullPointerExceptions on:
[java]
public void collision(PhysicsCollisionEvent event) {
System.out.println(event.getNodeA().getName());
}
[/java]

the second my character’s feet touch the ground. It is as if the other objects in the scene (not just GhostControlls) are calling the collision() method but don’t actually have values, because they have no ghost control?

<br>
EDIT:

[java]
public void collision(PhysicsCollisionEvent event) {
System.out.println(event.getNodeB().getName());
}
[/java]
Seems to print objects fine constantly. The game operates, and the print statement continues to update the collision of objects (including Scene nodes?). The second I try to do a print statement for getNodeA() it yields a nullPointerException

Instead:
System.out.println(event.getNodeA());

I see what you mean, Without the .getName().

That is returning only Bullet, the Geometry box i created or null.

Well if its ‘null’ and there is no object then what is with the collision detection?

I can work with null, when I know it’s null. Thanks so much pspeed. Sorry for being such a neophyte, but I do appreciate your patience and help!

I managed to get this to work. I just have to make sure the colliding objects aren’t null. I don’t understand why something doesn’t exist, if there’s a collision there should be an object colliding but shrug

[java]
public void collision(PhysicsCollisionEvent event) {
if(event.getNodeB() != null && event.getNodeA() != null){
if(event.getNodeA().getName().equals(“Bullet”) &&
event.getNodeB().getName().equals(“Objective”)){
System.out.println(“pass 1”);
}
[/java]

Hi, I am a complete noob, so forgive me if I don’t answer your question correctly. I had a similar problem, and after some debugging got it to work. I have a question, on your “collision” method, when you invoke event.getNodeB().getName().equals(“Bullet”)) your method will look for an object associated with the String “Bullet”; I did not see that instantiated anywhere in your code. Just like when you say
if (event.getNodeA().getName().equals(“Objective”)); your code will listen for any collisions involving your Objective Geometry, per the String that identifies that object as below:
((Geometry objective = new Geometry(“Objective”, box))) what object instantiated by the String “Bullet” are you listening for? did you initialize it in a static block? if not, maybe your bullet has not been initialized, just a thought.

Thanks for the feedback. I was only posting the GhostControl code, but I have all my other objects instantiated and named elsewhere in the code. I do have a Bullet and Objective object properly named. I got it to work