I am trying to do a little tower defense game. If I have a tower who has range of 10 what is the best way to do a collision detection for Enemies 360 degrees around the tower?
Do I do 360 ray traces? or is there a sphere collision or something that I can call?
Thanks,
Greg
You can use a sphere bounding box with the wanted radius. From this you can check if there’s anything inside and/or intersecting it.
You can use a GhostObject to track the overlapping physics objects but you have to use physics collision shapes for that. Else, you can use a sphere geometry and collideWith() the rootNode to check for overlaps. If thats not the solution I guess given the size of your levels it would always be faster simply checking all objects if they are in range than doing complicated checks.
I tried this
[java]CollisionResults results = new CollisionResults();
float radius = 2.0f;
Vector3f center = Vector3f.ZERO;
TDApplication.getInstance().getRootNode().collideWith(new BoundingSphere(radius,center ), results);
for(CollisionResult collisionResult : results){
System.out.println("Collision Result" +collisionResult.getGeometry().getName() );
}[/java]
Getting Java Exception
[java]
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
com.jme3.collision.UnsupportedCollisionException
at com.jme3.bounding.BoundingSphere.collideWith(BoundingSphere.java:807)
at com.jme3.collision.bih.BIHNode.intersectWhere(BIHNode.java:218)
at com.jme3.collision.bih.BIHTree.collideWithBoundingVolume(BIHTree.java:444)
at com.jme3.collision.bih.BIHTree.collideWith(BIHTree.java:457)
at com.jme3.scene.Mesh.collideWith(Mesh.java:846)
at com.jme3.scene.Geometry.collideWith(Geometry.java:338)
at com.jme3.scene.Node.collideWith(Node.java:494)
at com.scriptblocks.td.model.Tower.inRange(Tower.java:44)
at com.scriptblocks.td.model.Tower.simpleUpdate(Tower.java:29)
at com.scriptblocks.td.TDApplication.simpleUpdate(TDApplication.java:90)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:255)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:144)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:218)
at java.lang.Thread.run(Thread.java:662)
[/java]
You have to do spatial.collideWith(BoundingVolume), not the other way round.
Edit: Duh, you did that… Do you have any funny geometries in your scene? Like not created by jme?
Nope just Boxes
I’m not getting something I suppose but try with a full sphere spatial.
Edit: It could very well be that sphere vs world collisions are not implemented. In that case you’d have to use bullet for collisions. Basically its just attaching a kinematic RigidBodyControl to each box… It will use the most efficient box shape by default if you use normal boxes. Then you can go about using a GhostControl with sphere collision shape for overlaps.
Yeah I dont think BoundingSphere has been finished yet. It does a check for instanceof Ray and fails on everything else
i switched to
[java]
CollisionResults results = new CollisionResults();
Vector3f center = this.getWorldTranslation();
TDApplication.getInstance().getRootNode().collideWith(new BoundingBox(center, range,0.1f,range ), results);
[/java]
but
[java] Vector3f pt = collisionResult.getContactPoint();[/java]
pt returns null
Thanks for any help.
I’m pretty sure that only Rays will work like you want. There is no such thing as one contact point with a bounding box.
You may have to do your own sphere->sphere calculations as a “broad phase” and then use ray intersections for things that collide in the broad phase.
When you check collision against box/sphere, it checks it for every triangle
You can just do a Vector3f.length() calculation between the two nodes…
e.g. if( Tower.myNode.getWorldLocation().subtract(Enemy.myNode.getWorldLocation()).length() < 10 ) Tower.Fire(Enemy);