1

for IndexOutOfBoundsException:

Hi i'm making a space invader like game and i have a problem when a bullet collides with the enemy. Here is the code:

for (int i = 0; i < enemies.size(); i++) {
 for (int j = 0; j < bullets.size(); j++) {
 if (collidesWith(bullets.get(j), enemies.get(i))) { //Line 81 The Error Occurred here
 enemies.remove(i);
 bullets.remove(j);
 addScore(1);
 }
 }
}

Code for the Colliding:

public static boolean collidesWith(Entity collider, Entity collided) {
 Rectangle hitBox1 = collider.getHitbox();
 Rectangle hitBox2 = collided.getHitbox();
 return hitBox1.intersects(hitBox2);
}

Code for the Hitbox:

@Override
public Rectangle getHitbox() {
 return new Rectangle(getX(), getY(), getWidth(), getHeight());
}

The Error Messages:

Exception in thread "Thread-4" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at io.github.kjordo711.game.Main.run(Main.java:81)
at java.lang.Thread.run(Thread.java:724)

I think the error cause by 2 or more bullets hits the enemy

for OutOfMemoryError:

The Player can shoot too many bullets at once if they hold Space the bullet will keep shooting without delaying i could limit the bullet spawning but the problem is even with 10 bullets max on screen the error still occur, i tried to delay it with

Thread.sleep(500);

but it just sleep all the game thread

asked Oct 6, 2013 at 11:15
0

3 Answers 3

3

It's because you're removing object within the loops, which is not correct and besides ArrayIndexOutOfBoundsException this can cause a ConcurrentModificationExcetion, also.

When you're supposed to remove an object from a collection, consider using the java.util.Iterator interface.

Iterator<Enemy> enemiesIterator = enemies.iterator();
Iterator<Entity> bulletsIterator = bullets.iterator();
while (enemiesIterator.hasNext()) {
 Enemy nextEnemy = enemiesIterator.next();
 while(bulletsIterator.hasNext()) {
 Entity nextBullet = bulletsIterator.next();
 if (colliesWith(nextBullet, nextEnemy) {
 enemierIterator.remove();
 bulletsIterator.remove();
 addScore(1);
 }
 }
}
answered Oct 6, 2013 at 11:20
Sign up to request clarification or add additional context in comments.

2 Comments

Well it works but if i used Iterator<Entity> i got an error that say Type missmatch: cannot covert from Iterator<Enemy> to Iterator<Entity>
Well, I assumed it should be parametrized by Entity from the signature of the collidesWith() method. Anyway, I'm glad it works. Note that I'm not aware of what object are you collections parametrized with. :)
2

The problem is that you remove objects inside your nested loops. Once you remove an enemy at i, the list of enemies becomes shorter by one. If i happens to be equal to the old length of enemies, subsequent calls to enemies.get(i) are going to cause an exception. Since the inner loop does not re-check i, this situation is possible. Adding a guard for that and iterating backwards (something that you do when items could be removed as you go) should take care of the exception and avoid skipping collision checks on removals:

for (int i = enemies.size()-1 ; i >= 0 ; i--) {
 for (int j = bullets.size()-1 ; j >= 0 && i < enemies.size() ; j--) {
 if (collidesWith(bullets.get(j), enemies.get(i))) {
 enemies.remove(i);
 bullets.remove(j);
 addScore(1);
 }
 }
}
answered Oct 6, 2013 at 11:19

3 Comments

The guard approach removes the exception, but can make an enemy skipped for checking when one of them is removed.
"If there's no bullet to check against that enemy" - you can't guarantee that: Consider enemy 0 is hit and gets removed, then the enemy that was previously number 2 is the next to be checked. Just that an enemy was destroyed does not mean that there would not be any more enemies and bullets.
@kiheru Ah, you're right, the common issue of removing while iterating forward is still there. I reversed the order of iteration to fix that. Thanks!
0

I'll answer your concern about your second problem: using Thread.sleep(...) will block the current Thread, which probably is the EDT, freezing your whole game. If you want to avoid firing too many bullets, you should use System.currentTimeMillis() for each Space keystroke and compare it to the last one that actually fired a bullet:

static final int RECOIL = 500; // Minimum ms to wait between two shots
long lastShotMs = 0;
void fireBullet() { // Called when spacebar is pressed
 long shotMs = System.currentTimeMillis();
 if (shotMs - lastShotMs < RECOIL)
 return;
 lastShotMs = shotMs;
 doFireBullet(); // Perform the bullet-firing
}
answered Oct 6, 2013 at 11:45

2 Comments

it doesn't work i tried it like this 'code'public void shootBulletDelay() { long shotMs = System.currentTimeMillis(); if (shotMs - lastShotMs < SHOOT_PERIOD) { return; } lastShotMs = 0; shootBullet(); } public void shootBullet() { if (isAlive()) { playSound("/io/github/kjordo711/game/sound/bullet.wav", 0); Bullet b = new Bullet(x + 30, y - 12); bullets.add(b); Thread t = new Thread(b); t.start(); } }'code'
@HansFrank it should be lastShotMs=shotMs. Sorry I changed the variable name at the last minute and forgot one place. I've edited my answer.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.