Обнаружение столкновений в Java-игре?

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

6 ответов

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

В прошлом я делал так, чтобы предоставить изображение и маску для каждого объекта. Так, например, такой объект, как космический корабль Юпитер 2 из Lost in Space, будет иметь следующее изображение и маску:

     X            00000100000
  XXXXXXX         00111111100
 X       X        01111111110
X         X       11111111111
 X       X        01111111110
  XXXXXXX         00111111100
    XXX           00001110000

Изображение - это то, что передается на экран, но маска - это то, что используется для обнаружения столкновений. Вы заметите, что цифры в маске - это, в основном, контур и содержание изображения.

Способ обнаружения столкновения:

  • проверьте, перекрываются ли прямоугольники. Если нет, не может быть никаких шансов столкновения.
  • В противном случае создайте прямоугольник объекта № 1, состоящий из его маски.
  • Построить еще один прямоугольник объекта 2, состоящий из его маски.
  • Побитовое И - перекрывающаяся часть прямоугольника 2 с прямоугольником 1.
  • Если в прямоугольнике 1 остались 1 бит, то возникла коллизия.

При этом учитываются "промахи", когда ограничивающие прямоугольники каждого объекта перекрываются, но не обязательно объект очерчивает себя. Побитовые операторы - эффективный способ обнаружить это.

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

....xx....
..xx..xx..
.x......x.
.x......x.
x........x
x........x
.x......x.
.x......x.
..xx..xx..
....xx.**y.....
       .y......
       yyyyyyyy
       .y......
       ..y.....

Вы можете видеть это, хотя прямоугольники перекрываются (см. **y) стрелка фактически не соприкасалась с воздушным шаром. Применяя побитовую операцию И к маскам, эти биты будут иметь нулевое значение, что приведет к невозможности столкновения.


И @kyoryu поднимает интересный момент в своем комментарии. Некоторые игры хорошо адаптируются к объектам, составленным из меньших прямоугольников, и вы можете упростить обнаружение столкновений на основе прямоугольных компонентов (не беспокоясь о совершенстве пикселей). Например, наш старый друг космический захватчик (фактически защитник против космических захватчиков в этой игре) может состоять из двух прямоугольников, X и Y с ракетами, сделанными из Z:

    YYYY                .Z.
    YYYY                .Z.
XXXXXXXXXXXX            .Z.
XXXXXXXXXXXX            ZZZ
XXXXXXXXXXXX            .Z.
XXXXXXXXXXXX

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

Это довольно легко сделать столкновение с коробками. Если вы посмотрите только на ось x, есть три возможных варианта размещения двух блоков:

  1. перекрывающий
  2. Первая коробка слева от второй
  3. Первая коробка находится справа от второй.

Если первый блок находится слева от второго, это означает, что его крайняя правая точка должна находиться слева от крайней левой точки второго блока.

first.right < second.left

Если первый блок находится справа от второго, его крайняя левая точка должна находиться справа от крайнего правого пункта второго блока.

first.left > second.right

Если ни один из них не соответствует истине, то поля перекрываются по оси x.

Затем вы можете повторить это для плоскости y (заменив верхнюю и нижнюю части на левую и правую), чтобы узнать, перекрываются ли прямоугольники и на оси y - если они это делают, они сталкиваются! И это действительно все, что вам нужно сделать для простых столкновений в 2d игре.

Большая проблема может возникнуть в зависимости от того, сколько у вас различных объектов, поскольку наивной реализацией обнаружения столкновений является алгоритм O(N^2).

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

c^2 = a^2 + b^2

Мы можем обнаружить столкновение между двумя кругами, зная, что если расстояние между центрами меньше, чем объединенный радиус, они должны сталкиваться, верно? Затем вы можете выполнить проверку столкновения следующим образом:

distX ^ 2 + distY ^ 2 <= (radius1 + radious2) ^ 2 == COLLISION!

distX и distY - это расстояние между центрами двух окружностей, а радиус radius1 + radius2 в квадрате может быть предварительно рассчитан, если размеры окружностей не меняются.

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

Определите X и Y обоих изображений, а затем выполните некоторые вычисления за вычетом ширины и высоты каждого изображения, если они имеют разный размер, чтобы получить правильные координаты x и y. Пример:

| -------
| |
| |
| |
| _______ |

`|
    |
    |
    |
спускаясь вниз



      | --------- |
      | |
      | |
      | |
      | --------- |
Минус ширина и высота, чтобы узнать правильные х и у


Если вы готовы сделать это, JBox2D - это удивительный физический движок, созданный для решения этой проблемы. Он обрабатывает всю физику для вас, и все, что вам нужно сделать, это нарисовать изображения, где он говорит вам.

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

Вы можете скачать его здесь.

Здесь также есть несколько видео по основам. Библиотека, которую он использует, немного "хиленькая", но вы можете легко понять основы.

Вы можете использовать встроенные в Java прямоугольные пересечения. Это работает даже для повернутых прямоугольников.

  1. Создайте прямоугольник и убедитесь, что он следует за вращением и положением объекта.

  2. Позвоните rectangle.intersects(Rectangle) Метод на каждом кадре, чтобы выяснить, пересекается ли он.

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

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