1
\$\begingroup\$

Here is the code of bomb:

private int x, y;
private Texture bTexture;
private boolean bomb_explode;

private Timer timer;
private TimerTask task;
private int timeLeft = 0;

private TileMap map;
public static List<Bomb> bombs = new ArrayList<Bomb>();

public Bomb(TileMap map, int x, int y) {
    this.map = map;
    this.x = x;
    this.y = y;
    bTexture = new Texture("bomb.png");
    bomb_explode = false;
    bombs.add(this);
    createTimer();
}

public void render(SpriteBatch batch, float delta) {
    batch.draw(bTexture, x * Settings.SCALED_TILE_SIZE, y * Settings.SCALED_TILE_SIZE,
        Settings.SCALED_TILE_SIZE, Settings.SCALED_TILE_SIZE);
    if(timeLeft > 1f) {
        bomb_explode = true;
    }
    if(bomb_explode) {
        for(int i = 0; i <= 1; i++) {
            if(x + i <= map.getWidth()) {
                batch.draw(new Texture("flame.png"), 
                    ((x + i) * Settings.SCALED_TILE_SIZE), y * Settings.SCALED_TILE_SIZE, 
                     Settings.SCALED_TILE_SIZE, Settings.SCALED_TILE_SIZE);
            }
            if(y + i <= map.getHeight()) {
                batch.draw(new Texture("flame.png"), x * Settings.SCALED_TILE_SIZE, 
                   ((y + i) * Settings.SCALED_TILE_SIZE), Settings.SCALED_TILE_SIZE, 
                   Settings.SCALED_TILE_SIZE);
            }
            if(x - i >= 0) {
                batch.draw(new Texture("flame.png"), 
                    ((x - i) * Settings.SCALED_TILE_SIZE), y * Settings.SCALED_TILE_SIZE, 
                    Settings.SCALED_TILE_SIZE, Settings.SCALED_TILE_SIZE);
            }
            if(y - i >= 0) {
                batch.draw(new Texture("flame.png"), x * Settings.SCALED_TILE_SIZE, 
                ((y - i) * Settings.SCALED_TILE_SIZE), Settings.SCALED_TILE_SIZE, 
                Settings.SCALED_TILE_SIZE);
            }
        }
    }

}

public void Boom() {
    bomb_explode = false;
    for(int i = 0; i <= 1; i++) {
        if(map.getTile(x, y).getPlayer() != null) {
            map.getTile(x, y).getPlayer().Die();
        }

        if(x + i <= map.getWidth() && map.getTile(x+i, y).getPlayer() != null) {
            map.getTile(x+i, y).getPlayer().Die();
        }

        if(x - i >= 0 && map.getTile(x-i, y).getPlayer() != null) {
            map.getTile(x-i, y).getPlayer().Die();
        }

        if(y + i <= map.getHeight() && map.getTile(x, y+i).getPlayer() != null) {
            map.getTile(x, y+i).getPlayer().Die();
        }

        if(y - i >= 0 && map.getTile(x, y-i).getPlayer() != null) {
            map.getTile(x, y-i).getPlayer().Die();
        }
    }
    bombs.remove(this);
}

public void createTimer() {
    timeLeft = 0;
    task = new TimerTask() {

        @Override
        public void run() {
            ++timeLeft;
            if(timeLeft > 3) {
                bomb_explode = true;
                Boom();
                clearTimer();
            }
        }
    };

    timer = new Timer();
    timer.schedule(task, 1, 500);
}

public void clearTimer() {
    timer.cancel();
    timer.purge();
    timer = null;
}

In the screen class, I'm rendering the bomb like this :

for(Bomb b : Bomb.bombs) {
    b.render(batch, delta);
}

Here is the error I'm getting:

Exception in thread "LWJGL Application" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at bomberman.screens.GameScreen.render(GameScreen.java:41)
at com.badlogic.gdx.Game.render(Game.java:46)
at bomberman.game.GameObject.render(GameObject.java:23)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:225)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)

How can I fix it?

\$\endgroup\$
2
  • \$\begingroup\$ I've suggested an edit to add your code to the question directly. You should always post your code using the code formatting block instead of posting a link to a pastebin snippet, in case the link dies in the future. Also, could we have your GameScreen.render() code as well? It seems this is where the problem is located. \$\endgroup\$
    – Charanor
    May 7, 2017 at 15:37
  • \$\begingroup\$ i've added the GameScreen.render() method. Thanks for your time ! \$\endgroup\$
    – clint rock
    May 7, 2017 at 15:48

1 Answer 1

1
\$\begingroup\$

Your problem (probably) comes from the fact that you call bombs.remove(this); in your bomb's Boom() method while you're iterating through your list. This will throw a ConcurrentModificationException. As stated in the javadocs:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

To circumvent this I quote John Skeet's answer:

  • Create a list of values you wish to remove, adding to that list within the loop, then call originalList.removeAll(valuesToRemove) at the end

  • Use the remove() method on the iterator itself. Note that this means you can't use the enhanced for loop.

For you this could look something like this:

// In your Bomb class
public static ArrayList<Bomb> bombs = ...;
public static ArrayList<Bomb> bombsToRemove = ...;

// In your Boom() method
bomb_explode = false;
for(int i = 0; i <= 1; i++) {
    ...
}
bombsToRemove.add(this);

// In your render() method
for(Bomb b : Bomb.bombs) {
    ...
}
Bomb.bombs.removeAll(Bomb.bombsToRemove);
Bomb.bombsToRemove.clear();

Hopefully this resolves the issue for you!

\$\endgroup\$
1
  • \$\begingroup\$ @clintrock if the answer solved your issue make sure to click the "tick" symbol on the answer (top left) to mark it as the correct answer :) \$\endgroup\$
    – Charanor
    May 7, 2017 at 17:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .