2015-05-24 7 views
3

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

Это класс. Соответствующий код в основном находится на строках 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) { 

} 
} 

ответ

2

Ваша проблема заключается в том, что вы используете переменную 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. Это, вероятно, приведет к вашей логике.

EDIT:

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

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

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

+0

@Calvin Вы также делаете предположения относительно размера списка «враг», поэтому при доступе к элементам этого списка исключение может быть выбрано. – Eran

+0

Ваши объяснения сделаны с тех пор, как бы то ни было, одна и та же ошибка продолжалась. Как изменить список врагов? Я изменил пересечение, если выражения выполняются 'if (bullCount.get (i) .getBounds(). Intersects (enemy.get (4) .getBounds())) {enemy.remove (4); bullCount.remove (я); я--; return; 'но единственное изменение - теперь враг исчезает до того, как будет выброшена ошибка. – Calvin

+0

@Calvin see edit – Eran