1

I am currently making a simple 2d game in java. I have created A controller class and created linked lists for zombies(enemies) and bullets. Then in my gameState class I am trying to use for each loops to loop through the linked lists and detect if there is a collision with the bullet and the zombie. However the way it is laid out below in my code example, only the enemy can be removed from the game, if I try to remove the bullet as well, the game crashes. I was wondering if I could get some ideas on how i can remove both entities after a collision occurs.

this is the error I get when the bullet collides with the enemy

Exception in thread "Thread-1" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at android.game.GameState.update(GameState.java:71)
at android.game.Game.update(Game.java:121)
at android.game.Game.run(Game.java:101)
at java.lang.Thread.run(Unknown Source)

In GameState class:

for(Zombie zombie : c.z)
    {
        if(player.getX() > zombie.getX()){
            zombie.setX(zombie.getX() + 1);
        }

        if(player.getX() < zombie.getX()){
            zombie.setX(zombie.getX() - 1);
        }

        if(player.getY() > zombie.getY()){
            zombie.setY(zombie.getY() + 1);
        }

        if(player.getY() < zombie.getY()){
            zombie.setY(zombie.getY() - 1);
        }

        if(player.getBounds().intersects(zombie.getBounds())){

            kills ++;
            c.removeZombie(zombie);
            System.out.println("kills" + kills);

        }

        for(Bullet bullet : c.b){
            if(zombie.getBounds().intersects(bullet.getBounds())){
                //c.removeBullet(bullet);
                c.removeZombie(zombie);
                kills++;

                System.out.println("kills" + kills);        
            }

        }

    }

Controller class:

public class Controller {

LinkedList<Bullet> b = new LinkedList<Bullet>();
LinkedList<Zombie> z = new LinkedList<Zombie>();

Bullet TempBullet;
Zombie TempZombie;

public Controller(){
    addZombie(new Zombie (200,600));
    addZombie(new Zombie (400,650));
}

public void tick(){
    for(int i = 0; i<b.size(); i++){
        TempBullet = b.get(i);

        TempBullet.tick();
    }

    for(int i = 0; i<z.size(); i++){
        TempZombie = z.get(i);

        TempZombie.update();
    }


}

public void draw(Graphics g){
    for(int i = 0; i < b.size(); i++){
        TempBullet = b.get(i);

        TempBullet.draw(g);
    }

    for(int i = 0; i < z.size(); i++){
        TempZombie = z.get(i);

        TempZombie.render(g);
    }

}

public void addBullet(Bullet block){
    b.add(block);
}

public void removeBullet(Bullet block){
    b.remove(block);
}

public void addZombie(Zombie block){
    z.add(block);
}

public void removeZombie(Zombie block){
    z.remove(block);
}
}
Aleksandr M
  • 24,264
  • 12
  • 69
  • 143
Ciaran
  • 697
  • 1
  • 12
  • 35
  • "the game crashes" is not a very precise description. I presume you get an exception message of some kind. – khelwood Jul 19 '16 at 10:49
  • i edited the question – Ciaran Jul 19 '16 at 10:55
  • Take out update logic from GameState, and put it into respective `update` method in zomby / bullet / whatever classes. Create `isDestroyed` flags, and set it to true when you detect collision and want to destroy things as a result. Finally, in your GameState, you iterate over your zombies / bullets, call their update method, check their `isDestroyed` flag, and if it is true, you remove them from the collection. – Coderino Javarino Jul 19 '16 at 11:01

3 Answers3

3

Use an Iterator to go through your list, and use the remove() method to remove the current element from your Collection:

for(Iterator<Zombie> it = c.z.iterator(); it.hasNext(); ) {
    Zombie zombie = it.next();
    if (collisionWithBullet)
        it.remove();
}
Matthieu
  • 2,736
  • 4
  • 57
  • 87
1

You can not use a for each loop for checking the collision with bullet and then remove the same bullet simultaneously. Instead, you could try marking the bullets for removal and then remove them after collision detection for each loop is finished.

Anupam Jain
  • 101
  • 10
1

ConcurrentModificationException happens if you remove element while doing for-each loop. One way to work around this is to change the loop to an indexed one:

for (int i = c.z.size() - 1; i >= 0; i--) {
    Zombie zombie = c.z.get(I);

Deleting a zombie should be safe then, without having to store zombies to remove in a separate collection.

Slavcho
  • 383
  • 1
  • 7