Я получаю «IndexOutOfBounds» в моей игре «Кометы против космического корабля» - PullRequest
1 голос
/ 13 марта 2020

Я начал разрабатывать игру в стиле «Космический корабль против комет» на прошлой неделе, и теперь я остановился.

Цель игры - стрелять в кометы до того, как они пройдут мимо вашего корабля. Вы заставляете кометы взрываться, стреляя в них. Простая идея!

Однако иногда, когда я играю, я получаю ошибку "IndexOutOfBounds" . Это почти всегда появляется, когда я не стреляю некоторое время (размер моих снимков ArrayList равен 0), а когда я стреляю, и он сталкивается, он падает.

Так что у меня есть некоторые ошибка в моем коде, но я действительно не вижу ее. Теперь я надеюсь, что один из вас поймет, почему это происходит, и избавит меня от дальнейших ошибок "IndexOutOfBounds"! :)

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

ИГРОВОЙ КЛАСС

    if(!Game.player.getShots().isEmpty() && !comet.getComets().isEmpty()) { //Om de är tomma så ignorera

        for(int x = 0; x < Game.player.getShots().size(); x++) {    //Shots X

            if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()) {



                for(int y = 0; y < comet.getComets().size(); y++) {     //Comets Y

                    if(comet.getComets().get(y).intersects(Game.player.getShots().get(x)) && !comet.getComets().isEmpty() && !Game.player.getShots().isEmpty()) {   
    //the for loop above is the line that won't compile sometimes

                        comet.getComets().remove(y);
                        Game.player.getShots().remove(x);   

                        score++;
                    }

                }
            }

        }
    }

    //Comet spawn timer
    comet.addComets();

    //Move the comets and shots!
    Game.player.moveShots();
    comet.moveComets();
    repaint();

КОМЕТА КЛАССА

public ArrayList<Rectangle> getComets() {

    return comets;
}

public void moveComets() {
    if(!comets.isEmpty()) {

        for(int x = 0; x < comets.size(); x++) {

            comets.get(x).x -= cometSpeed;
        }
    }

}

КЛАСС ИГРОКА (Снимки в этом классе)

public void fire() {


    shots.add(new Rectangle(x + player.width, y + 23, shotWidth,shotHeight));
}
public ArrayList<Rectangle> getShots() {

    return shots;

}

public void moveShots() {
    if(!shots.isEmpty()) {
        for(int x = 0; x < shots.size(); x++) {

            shots.get(x).x += fireSpeed;
        }
    }
}

Сохранить в Имейте в виду, что кометы и выстрелы являются «ArrayList вне объекта Rectangle»

Я предоставлю скриншоты ошибок и картину игры ниже!

Picture of the GUI

Picture of the error in console

В приведенном выше коде помечена строка ошибки, оператор if должен блокировать ее сбой (I думал).

Заранее спасибо! Вся помощь приветствуется! :)

Ответы [ 3 ]

2 голосов
/ 13 марта 2020

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

if( x < Game.player.getShots().size() && comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {

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

Лучшая производительность if будет:

if(!Game.player.getShots().isEmpty() || !comet.getComets().isEmpty()) { 
//if one of them is empty, won't be intersections

        for(int x = 0; x < Game.player.getShots().size(); x++) {    //Shots X
                for(int y = 0; y < comet.getComets().size() && x < Game.player.getShots().size(); y++) {
 //Comets Y only if the shoot still available

                    if(comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {   
    //the for loop above is the line that won't compile sometimes

                        comet.getComets().remove(y);
                        Game.player.getShots().remove(x);   

                        score++;
                        y = 0; // if you don't set the y = 0 the next shoot (as you removed the x, getShots.get(x) would be the x + 1 shoot) will only evaluate for the comets after y, won't evaluate the firsts comets at the array.
                    }

                }
            }

        }
2 голосов
/ 13 марта 2020

Попробуйте настроить здесь if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()). Вы проверяете массив комет дважды.

Дайте мне знать, если он работает.

1 голос
/ 13 марта 2020

Является ли этот код многопоточным? Мне также интересно, почему вы проверяете comet.getComets().isEmpty() так много раз.

Я предполагаю, что вы манипулируете ArrayList в какой-то другой части вашего кода. Причина, по-моему, в том, что вы проверяете размер списка несколько раз и потому, что в пределах для l oop вы удаляете только в конце, так что это не должно быть проблемой.

Например, если вы запускаете этот метод в двух потоках одновременно, ArrayList может быть проверен в одной точке, но может уменьшиться после проверки размера. затем, когда, например, размер был 10, но стал 9, но вы все еще пытаетесь удалить x со значением 10, вы получите ошибку выхода за границы.

...