Проблемы столкновения объектов

Я делаю основную игру, и она почти готова. Я пытался сделать столкновение объектов и начал получать исключения IndexOutOfBounds. Я думаю, это означает, что мои списки массивов, в которых я храню объект, ни на что не указывают, но я не знаю, почему это происходит, и как это исправить. Я также понимаю, что это вопрос, который задают многие люди, однако я не смог понять его, посмотрев другие посты. Я не очень хорошо понимаю arrayLists.

Вот класс. Соответствующий код в основном находится в строках 75 - 99. Буду признателен за любую помощь, которую вы можете оказать!

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) {

}
}

1 ответ

Решение

Ваша проблема в том, что вы используете size переменная для определения количества итераций следующего цикла. size инициализируется в bullCount.size(), но если вы удалите элемент из bullCountразмер этого списка становится меньше, и цикл IndexOutOfBoundException:

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

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

Вам нужно сделать две вещи, чтобы исправить цикл:

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
    }

Кроме того, звонит enemy.get(2) без проверки этого enemy.size()>2 может бросить то же исключение. И зовет enemy.remove(2) заставит элемент, который был в индексе 3, переместиться в индекс 2. Это, вероятно, испортит вашу логику.

РЕДАКТИРОВАТЬ:

Ваша логика, вероятно, будет работать лучше, используя вложенный цикл:

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;
        }
    }
}

Это предполагает, что пуля может уничтожить только одного врага.

Другие вопросы по тегам