Java столкновение не работает с боков - PullRequest
0 голосов
/ 07 мая 2019

Я делаю Java-игру, как разбивать кирпичи. У меня уже есть обнаружение столкновений. Но теперь я хочу уничтожить некоторые блоки, если их HP равен 0. Если я касаюсь своего блока ниже или выше, он работает нормально, каждый шар отдает 1 HP в блок. Но если я коснусь блока слева или справа, блок разрушится, несмотря на то, что у него осталось HP.

Каждый раз, когда я касаюсь блока, я проверяю положение своего мяча по сравнению с блоком. Но справа и слева я не понимаю, почему это не работает.

Я также не уверен в том, как я уничтожаю блоки ... Я имею в виду, я храню все блоки на карте. Я получаю текущую волну моего блока (линия так). А затем я сравниваю указанный в параметре блок со всеми блоками этой линии. Это верно?

for (Ball ball : ballList) {
            for (List<Bloc> wave : mapBlocs.values()) {
                for (Bloc bloc : wave) {
                    if (ball.getBounds().intersects(bloc.getBounds())) {
                        if (ball.getPosY() <= bloc.getPosY() + bloc.getHeight()) {
                            ball.setVelocityY(-ball.getVelocityY());
                            ball.setPosY(ball.getPosY() + ball.getVelocityY());
                            bloc.setHardness(bloc.getHardness() - 1);
                            System.out.println("below");
                        } else if (ball.getPosY() + ball.getHeight() >= bloc.getPosY()) {
                            ball.setVelocityY(-ball.getVelocityY());
                            ball.setPosY(ball.getPosY() + ball.getVelocityY());
                            bloc.setHardness(bloc.getHardness() - 1);
                            System.out.println("above");

                        } else if (ball.getPosX() + ball.getWidth() <= bloc.getPosX()) {
                            ball.setVelocityX(-ball.getVelocityX());
                            ball.setPosX(ball.getPosX() + ball.getVelocityX());
                            bloc.setHardness(bloc.getHardness() - 1);
                            System.out.println(bloc.getHardness());
                            System.out.println("left");

                        } else if (ball.getPosX() >= bloc.getPosX() + bloc.getWidth()) {
                            ball.setVelocityX(-ball.getVelocityX());
                            ball.setPosX(ball.getPosX() + ball.getVelocityX());
                            bloc.setHardness(bloc.getHardness() - 1);
                            System.out.println(bloc.getHardness());
                            System.out.println("right");
                        }
                        if (bloc.getHardness() == 0) {
                            destroyBlocs(bloc);
                    }


                    }
                }

И мой метод destroyBlocs:

    private void destroyBlocs(Bloc bloc) {

        List<Bloc> list = mapBlocs.get(bloc.getWaveNumber());
        for (Bloc a : list) {
            if (a.equals(bloc)) {
                list.remove(bloc);
            }
        }

    }

Как я могу исправить? И заранее спасибо!

@ UPDATE

Когда я тестирую свое приложение, когда я ударяю блок по бокам, мяч выполняет другое действие. Он проходит через блок, так что он подсчитывает бесконечность попаданий, поэтому я думаю, что поэтому блок мгновенно исчезает, поэтому мой вопрос: почему я не получаю отскок, когда бью блок со стороны?

Ответы [ 2 ]

1 голос
/ 08 мая 2019

Хм, я еще раз взглянул на ваш код и, возможно, обнаружил ошибку (отладка должна это подтвердить): ваши условия, похоже, проверяют, находится ли шарик вне блока.

Предполагая, что Ball и Bloc являются компонентами качания, координата 0/0 будет означать верхний левый угол и, следовательно, положительный y будет вниз.

Таким образом, края блока могут быть частично определены как

  • вверху: block.y
  • внизу: block.y + block.height
  • left: block.x
  • right: block.x + block.width

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

  1. «внизу»: ball.y <= block.y + bloc.height </li>
  2. "выше": ball.y + ball.height> = block.y
  3. "влево": ball.x + ball.width <= block.x </li>
  4. "right": ball.x> = block.x + block.width

Для простоты будем считать, что шар - это просто точка, то есть with и height равны 1Таким образом, мы проигнорируем размер шара и просто используем его положение (которое в любом случае представляет пиксель шара) и упростим ваши уравнения (которые могут быть отклонены на 1 btw):

  1. «ниже»: шар.y <= block.y + bloc.hвосемь </li>
  2. "выше": ball.y> = block.y
  3. "влево": ball.x <= block.x </li>
  4. "вправо": ball.x> = block.x + block.height

Теперь давайте визуализируем те, у которых есть несколько стрелок, чтобы указать, где они будут истинны:

   +----------+  ---
   |          |   | (2)
   |  Block   |   V        ^
   |          |            | (1)
   +----------+           ---

<--|          |-->
 (3)           (4)

Основная проблема сейчас заключается в том, что вы 'повторяю эти условия по порядку.Что произойдет, если мяч попал в блок со стороны?Условие 1, скорее всего, уже будет выполнено, и вы просто измените y-условие.Если он все еще находится внутри блока, то условие 1 или 2 все равно будет выполнено, и вы вернете y-условие обратно.

Однако есть также проблема с условиями 3 и 4:

Из-за проверки пересечения ваше исходное условие 3 может быть верным только в том случае, если мяч находится справа от левого края, что может вообще не быть ударом.Если это немного правее, условие больше не будет верным.

Давайте сделаем пример с шаром шириной 5 и блоком с x-позицией 10. Таким образом, ваше условие ball.x + ball.width <= block.x будет равно ball.x + 5 <= 10.Это может быть верно только для ball.x <= 5. Однако для любого ball.x <5 вы получите правильную границу 9 или меньше для шара, что означает, что он не пересекает блок. </p>

Условие 4 аналогично: предположим, что блок имеет ширину 20 и позицию x, равную 10. Таким образом, ball.x >= block.x + block.width становится ball.x >= 30 (10 + 20).Это означает, что это будет верно только в том случае, если шар имеет х-позицию ровно 30, но это не будет означать пересечение.

0 голосов
/ 13 мая 2019

После проверки объяснения @Thomas я получил это решение:

                    if (ball.getVelocityX() > 0) {
                        if (ball.getPosX() < bloc.getPosX()) {
                            ball.setVelocityX(-ball.getVelocityX());
                            ball.setPosX(ball.getPosX() + ball.getVelocityX());
                            bloc.setHardness(bloc.getHardness() - 1);
                            // left hit
                        } else {
                            ball.setVelocityY(-ball.getVelocityY());
                            ball.setPosY(ball.getPosY() + ball.getVelocityY());
                            bloc.setHardness(bloc.getHardness() - 1);
                            // below hit
                        }
                    } else {
                        if (ball.getPosX() < bloc.getPosX() + bloc.getWidth()) {
                            ball.setVelocityY(-ball.getVelocityY());
                            ball.setPosY(ball.getPosY() + ball.getVelocityY());
                            bloc.setHardness(bloc.getHardness() - 1);
                            // above hit
                        } else {
                            ball.setVelocityX(-ball.getVelocityX());
                            ball.setPosX(ball.getPosX() + ball.getVelocityX());
                            bloc.setHardness(bloc.getHardness() - 1);
                            // right hit
                        }
                    }
...