I’ve been working on a classic 2D Space Invaders-style game in Java. It’s been a fun journey missiles firing, enemies descending, and that nostalgic arcade feel slowly coming to life.
To manage game objects like enemies and missiles, I decided to use LinkedList
. Everything was working smoothly until I hit a collision literally.
The moment a missile collided with an enemy, my game crashed with this exception:
java.util.ConcurrentModificationException
It took me a while to figure out what was going on. In this blog post, I’ll walk you through the problem, explain why it happened, and show how I fixed it plus some bonus features I added to make the game more fun.
The Original Code
Here’s what my original checkCollisions()
method looked like:
private void checkCollisions() {
ListIterator<Enemy> iterEnemies = enemiesLeft.listIterator();
while(iterEnemies.hasNext()) {
Enemy e = iterEnemies.next(); // ERROR OCCURS HERE
ListIterator<Missile> iterMissiles = missiles.listIterator();
while(iterMissiles.hasNext()) {
Missile m = iterMissiles.next();
if(e.doesIntersect(m)) {
enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e))); //
missiles.remove(m); //
}
}
}
updateScore();
}
Every time a missile hit an enemy, the game threw an error and crashed. At first, I thought maybe it was a null pointer or bad logic but then I saw the actual exception.
What Is the Error and Why Does It Happen
ConcurrentModificationException
Explain
This error occurs when you modify a collection while iterating over it, but not using the iterator’s own remove()
method.
In my code, I was iterating through enemiesLeft
and missiles
, but modifying those lists directly with:
enemiesLeft.remove(...);
missiles.remove(...);
This broke the internal state of the iterators and triggered the exception.
The Fix and Improve Code
I rewrote the method to safely remove elements using the iterator’s own remove()
method. Here’s the corrected version:
private void checkCollisions() {
ListIterator<Enemy> iterEnemies = enemiesLeft.listIterator();
while (iterEnemies.hasNext()) {
Enemy e = iterEnemies.next();
ListIterator<Missile> iterMissiles = missiles.listIterator();
while (iterMissiles.hasNext()) {
Missile m = iterMissiles.next();
if (e.doesIntersect(m)) {
iterEnemies.remove(); // Safe removal
iterMissiles.remove(); // Safe removal
enemiesKilled.add(e); // Track the kill
updateScore(); // Update score
playExplosionEffect(e); // Optional: explosion
playHitSound(); // Optional: sound
break; // Exit inner loop after a hit
}
}
}
checkGameOver(); // Optional: check for end of game
}
By using iterator.remove()
for both enemies and missiles, the crash disappeared. Simple fix, but easy to miss!
Extra Feature I Added
After fixing the core issue, I decided to level up the gameplay with some added effects and logic.
Explosion Animation
private void playExplosionEffect(Enemy e) {
Explosion explosion = new Explosion(e.getX(), e.getY());
activeExplosions.add(explosion);
}
Call it in the collision block:
playExplosionEffect(e);
Sound Effect on Hit
private void playHitSound() {
SoundPlayer.play("explosion.wav");
}
Add this too:
playHitSound();
Enemy Respawn
Instead of removing enemies permanently, I could just respawn them:
e.setPosition(randomX(), startY);
But I kept it optional since sometimes you really just want the enemy gone.
Game Over Condition
private void checkGameOver() {
if (enemiesLeft.isEmpty()) {
gameRunning = false;
showGameOverScreen();
}
}
And call it after the collision loop:
checkGameOver();
Final Thought
Fixing the ConcurrentModificationException
taught me a valuable lesson: never modify a collection while iterating unless you use the iterator’s methods.
It was a frustrating bug at first, but the fix was straightforward once I understood the cause. And it turned out to be a great opportunity to add features like explosions, sound, and game-over logic.
Now my Space Invaders clone not only runs smoothly but is also way more fun to play.