Object collision problems

I'm making a base game and it's almost done. I was trying to do object collision and started getting IndexOutOfBounds exceptions. I think this means that my arrays that I store in the object are not indicating anything, but I don't know why this is happening and how to fix it. I also understand that this is a question that many people are asking, however I have not been able to figure it out by looking at other posts. I am not very good at arrays.

Here is the class. The relevant code mostly refers to lines 75 - 99. Any help you can give would be appreciated!

package Sprites;


import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;


public class Player implements KeyListener{

private int x;
private ArrayList<Integer> keysDown;
private ArrayList<Bullets> bullCount;
private ArrayList<Enemy> enemy;
private Bullets b;
private Enemy e;
private int size;
long start;
long elapsed;
boolean run;

public int getbY() {
    return b.getY();
}
public int getbX() {
    return b.getX();
}

public Player(int x1) {
    x = x1; //initial spawns of player
    run = true;
    keysDown = new ArrayList<Integer>();
    bullCount = new ArrayList<Bullets>();
    enemy = new ArrayList<Enemy>();
    start = System.nanoTime();
    for (int i = 240; i < 800; i = i + (800/10)){
        e = new Enemy(i, true);
        enemy.add(e);
        if (enemy.size() > 5) {
            enemy.remove(5);
        }
    }

}

public boolean isRun() {
    return run;
}
public void update() {
    move(); //player movement

    size = bullCount.size(); //bullet updates
    if (size > 0) {
        for(int i = 0; i < size; i++)  {
            bullCount.get(i).update();
            if (bullCount.get(i).getY() < 0) {
                bullCount.remove(i);
                return;
            }
        }
    }//end of bullet spawns

    for(int i = 0; i < 5; i++) {
        if (enemy.get(i).getY() >= 535) //end game
            run = false;
    }

    if (enemy.size() > 0) {
        for (int i = 0; i < 5; i ++) { //update enemys
            enemy.get(i).update();
        }
    }

    //bullet collision
    for (int i = 0; i < size; i++) {

        if(bullCount.get(i).getBounds().intersects(enemy.get(0).getBounds())) {
            enemy.remove(0);
            bullCount.remove(i);
        }

        if(bullCount.get(i).getBounds().intersects(enemy.get(2).getBounds())) {
            enemy.remove(2);
            bullCount.remove(i);
        }

        if(bullCount.get(i).getBounds().intersects(enemy.get(1).getBounds())) {
            enemy.remove(1);
            bullCount.remove(i);
        }

        if(bullCount.get(i).getBounds().intersects(enemy.get(3).getBounds())) {
            enemy.remove(3);
            bullCount.remove(i);
        }

        if(bullCount.get(i).getBounds().intersects(enemy.get(4).getBounds())) {
            enemy.remove(4);
            bullCount.remove(i);
        }

    }

}


public ArrayList<Enemy> getEnemy() {
    return enemy;
}
public void move() {

    if(keysDown.contains(KeyEvent.VK_A)) {
        if (x > 0 + 10) {
        x = x - 3;
        }
    }
    if(keysDown.contains(KeyEvent.VK_D)){
        if (x < 800 - 42) {
        x = x + 3;
        }
    }
    if (keysDown.contains(KeyEvent.VK_SPACE)) {

        elapsed = System.nanoTime() - start;

        if (elapsed > 185000000) {
        b = new Bullets(x);
        bullCount.add(b);
        start = System.nanoTime();
        }
    }
}

public ArrayList<Bullets> getBullCount() {
    return bullCount;
}

public int getPX() {
    return x;
}

public void keyPressed(KeyEvent e) {
    if (!keysDown.contains(e.getKeyCode()))
        keysDown.add(new Integer(e.getKeyCode()));
    }

public void keyReleased(KeyEvent e) {
    keysDown.remove(new Integer(e.getKeyCode()));

}

public void keyTyped(KeyEvent e) {

}
}

      

+3


source to share


1 answer


Your problem is that you are using a variable size

to determine the number of iterations of the next loop. size

is initialized to bullCount.size()

, but if you remove an element from bullCount

, the size of this list becomes smaller and the loop will throw IndexOutOfBoundException

:

for (int i = 0; i < size; i++) {

    if(bullCount.get(i).getBounds().intersects(enemy.get(0).getBounds())) {
        enemy.remove(0);
        bullCount.remove(i);
    }

      

You need to do two things to fix the loop:

for (int i = 0; i < bullCount.size(); i++) { // get the current size from the list

    if(bullCount.get(i).getBounds().intersects(enemy.get(0).getBounds())) {
        enemy.remove(0);
        bullCount.remove(i);
        i--; // if you remove an element, the indices of the following elements
             // are decremented, so you should iterate over the same value
             // of i in order not to skip an element
    }

      

Also, calling enemy.get(2)

without checking for what enemy.size()>2

might throw the same exception. And the call enemy.remove(2)

will force the element that was at index 3 to go to index 2. This will probably lead to your logic.



EDIT:

Your logic will probably perform better using a nested loop:

for (int i = 0; i < bullCount.size(); i++) {
    for (int j = 0; j < enemy.size(); j++) {
        if(bullCount.get(i).getBounds().intersects(enemy.get(j).getBounds())) {
            enemy.remove(j);
            bullCount.remove(i);
            i--;
            break;
        }
    }
}

      

This assumes that the bullet can only destroy one enemy.

+2


source







All Articles