Я заставил мало стрелять в них игра.. Это работает нормальное, но я хочу также реализацию, если огни пересекутся, то они исчезнут. Я имею два, перечисляют для маркеров Плеера и для компьютерных маркеров... Но если я имею больше маркеров от компьютера или инвертирую.Here мой цикл
for (int i = 0; i < cb.size(); i++) {
for (int j = 0; j < b.size(); j++) {
if (b.get(j).rect.intersects(cb.get(i).rect)) {
cb.remove(i);
b.remove(j);
continue;
}
if (cb.get(i).rect.intersects(b.get(j).rect)) {
b.remove(j);
cb.remove(i);
continue;
}
}
}
Это - моя игра который алгоритмы Уокинга... http://rapidshare.com/files/364597095/ShooterGame.2.6.0.jar
Я настоятельно рекомендую против играть со счетчиками цикла for из самого цикла. Вы осторожны сейчас, вы не будете осторожны позже («давайте попробуем взломать здесь для отладки») и в конечном итоге получите ошибки.
Одним из решений может быть:
thingsToRemove
thingsToRemove
и удалите (или установите значение null, или -1
или что-то еще) соответствующие элементы в списках cb
и b
Как указано в комментарии Карла, второе if должно быть лишним.
Что касается исключения IndexOutOfBounds, то оно вызвано следующим:
Когда пуля компьютера попадает в пулю игрока, вы удаляете обе пули из списков. Затем, используя continue
, вы продолжаете сравнивать ту же компьютерную пулю с оставшимися пулями игроков. Однако эта компьютерная пуля уже была удалена ранее! Поэтому я предлагаю вместо continue
использовать break
, тогда следующая компьютерная пуля будет проверяться на пересечение с пулями игроков.
Как намекает Роман в своем коде, вам следует еще уменьшить счетчик внешнего цикла, так как вы уменьшили размер списка, удалив одну из пуль. Следовательно, то, что раньше было пулей №3, на следующей итерации станет пулей №4. Поэтому после break
вам не нужен инкремент счетчика внешнего цикла.
Проблема с вашим кодом заключается в том, что вы изменяете размер списка cb всякий раз, когда находите пересечение, но затем продолжаете использовать тот же индекс. Например, если cb имеет 3 элемента, а b - 4, а третья (индекс = 2) компьютерная пуля пересекает пулю первого игрока, размер cb уменьшается до 2. Когда вы затем продолжаете проверять пулю второго игрока на третья компьютерная пуля, в cb осталось только два предмета, и игра вылетает.
Короче говоря, перебирать списки и одновременно изменять их сложно.
Еще одна вещь, которую следует учитывать, это то, что если, например, компьютерная пуля пересекается с двумя пулями игрока, все три из них должны быть удалены. Но если компьютерная пуля будет удалена, когда она встретит пулю первого игрока, пуля второго игрока останется.
На самом деле, цепочки пуль могут касаться друг друга, поэтому удаление чего-либо из списка до того, как вы сделаете все пересечения, может привести к неверным результатам.
После забавно долгого размышления об этом, вот что я бы сделал. Это гарантирует, что все, что нужно удалить, будет удалено и не зависит от изменения индекса.
ArrayList<Bullet> newB = new ArrayList<Bullet>(b);
ArrayList<Bullet> newCB = new ArrayList<Bullet>(cb);
for (Bullet pBullet : b) {
for (Bullet cBullet : cb) {
if (pBullet.rect.intersects(cBullet.rect)) {
newB.remove(pBullet);
newCB.remove(cBullet);
}
}
}
cb = newCB;
b = newB;
По моему мнению, вы можете написать так
for (int i = cb.size() -1; i >= 0 ; i--) {
boolean bremoved = false;
for (int j = b.size() -1 ; j >=0 ; j--) {
if (b.get(j).rect.intersects(cb.get(i).rect) ||
cb.get(i).rect.intersects(b.get(j).rect)) {
bremoved = true;
b.remove(j);
}
}
if(bremoved)
cb.remove(i);
}
the простейшая модификация, чтобы избежать логической ошибки:
for (int i = 0; i < cb.size(); i++) {
for (int j = 0; j < b.size(); j++) {
if (b.get(j).rect.intersects(cb.get(i).rect)) {
cb.remove(i--);
b.remove(j--);
}
}
}
Выполнение циклов в обратном направлении также должно помочь:
for (int i = cb.size() - 1; i >= 0; i--) {
for (int j = b.size() - 1; j >= 0; j--) {
РЕДАКТИРОВАТЬ: Это решение также может вызывать OOBE. Есть несколько необработанных случаев ... поэтому я должен порекомендовать одно из решений с более высоким рейтингом, а не это.