This is an answer that requires re-factoring of your code. It uses a known pattern to solve the problem of collisions and their detection. The GameObject
class that's assumed to exist should have the intersects
method available.
I would probably implement a collision listener interface with a collision dispatcher interface and have them used where I need them.
The interfaces would have methods like the following:
CollisionListener
is the interface that classes who need to know about collisions implement:
public interface CollisionListener {
// respond to a collision event
public void collisionEvent(CollisionEvent ce);
}
CollisionDispatcher
is the interface that classes who spot and notify about collisions to others implements, and other register to. This is probably your Game
class, or some main class of that sort.
interface CollisionDispatcher {
// add a collision listener who should be notified about each collision
public void addCollisionListener(CollisionListener cl);
// notify all subscribers (listeners) on collision event
public void notifyCollision(CollisionEvent ce);
}
I've added an example of a main that implements both. You may want something a bit different.
This is partial code:
private Collection<CollisionListener> cls;
private Collection<GameObject> gameObjects;
public Game(){
this.cls = new ArrayList<CollisionListener>();
this.addCollisionListener(this);
}
@Override
public void collisionEvent(CollisionEvent ce) {
System.out.println("Collision occured between "
+ ce.getGameObject1().toString() + " and "
+ ce.getGameObject1().toString());
}
@Override
public void addCollisionListener(CollisionListener cl) {
this.cls.add(cl);
}
@Override
public void notifyCollision(CollisionEvent ce) {
// notify to all listeners
for (CollisionListener cl : this.cls){
cl.collisionEvent(ce);
}
}
public void checkForCollisions(){
// check for collisions
for (GameObject go1 : gameObjects){
for (GameObject go2 : gameObjects){
// first part is ok cause we are looking for the same object
if (go1 != go2 && go1.interesects(go2)){
this.notifyCollision(new CollisionEvent(go1, go2));
}
}
}
}
The CollisionEvent
class can look like this:
public class CollisionEvent {
private GameObject go1, go2;
public CollisionEvent(GameObject g1, GameObject g2){
this.go1 = go1;
this.go2 = go2;
}
public GameObject getGameObject1(){
return this.go1;
}
public GameObject getGameObject2(){
return this.go2;
}
}
I hope you find this useful. If you do, read more.
A very useful optimization is to have only moving objects check for collisions as they move, this way you only need one loop like this:
// in GameObject
public void checkForCollisions(){
// check for collisions
for (GameObject go2 : gameObjects){
// first part is ok cause we are looking for the same object
if (this != go2 && this.interesects(go2)){
this.notifyCollision(new CollisionEvent(go1, go2));
}
}
}
You can also optimize (on the expense of design, why?) by notifying the object that's collided into directly, if that's the behavior you're looking for. This time the CollisionEvent can have only one parameter (re-factor the rest of the code accordingly), and the GameObject class will have the notifyCollision
and collisionEvent
methods:
// in GameObject
public void checkForCollisions(){
// check for collisions
for (GameObject go2 : gameObjects){
// first part is ok cause we are looking for the same object
if (this != go2 && this.interesects(go2)){
go2.notifyCollision(new CollisionEvent(go2));
}
}
}
You can also use invocation of methods on your listeners directly without the event object.