@Filipp42

Как определить коллизию квадратов?

Пишу простенькую игру, необходимо сделать обработку коллизий между двумя квадратами. Известны координаты их верхних левых углов, а также длины стороны каждого квадрата.
Как реализовать проверку коллизий?
  • Вопрос задан
  • 741 просмотр
Пригласить эксперта
Ответы на вопрос 4
trapwalker
@trapwalker
Программист, энтузиаст
Алгоритмов тут за вас никто придумывать не будет. Этот ресурс не для этого.
Учитесь решать такие задачи начиная с более простых.
Двухмерный случай с квадратами можно упростить понизив размерность задачи.
Представьте, что у вас не квадраты, а отрезки и не на плоскости, а на оси.
Нужно сформулировать булево выражение, которое будет истинно только в случае наложения отрезков (хотя бы частичного).
Вам уже предлагали в комментариях попробовать представить квадраты не размерами, а координатами границ. Если у вас возникнут трудности и с вычислением координат правых нижних углов, то у меня для вас плохие новости...
Попробуйте решить задачу для отрезков на оси, а потом подумать как расширить её для квадратов на плоскости.
Если на этом этапе ещё не очевидно решение, то начинать следует с более простого. Хотя, казалось бы, куда уж проще.
Ответ написан
Комментировать
wataru
@wataru Куратор тега Математика
Разработчик на С++, экс-олимпиадник.
Вот тут программисту и нужна математика (совсем чуть чуть).

Квадрат - это все точки (X, Y), которые удовлетворяют неравенствам:
x1 <= X <= x1 + w1
y1 <= Y <= y1 + w1


Пересечение двух квадратов - это точки, которые удовлетворяют одновременно каждой паре неравенств, т.е. удовлетворяют сразу четырем неравенствам:
x1 <= X <= x1 + w1
y1 <= Y <= y1 + w1
x2 <= X <= x2 + w2
y2 <= Y <= y2 + w2


Тут уже видно, что фактически есть пара неравенств на X, и есть пара неравенств на Y. Они независимые. Вот и получается, что пересечение можно искать отдельно по каждой оси.

Рассмотрим одну пару:
x1 <= X <= x1 + w1
x2 <= X <= x2 + w2


Вообще, такие системы неравнеств решают в школе, классе этак в 7.

Сконцентрируемся на левых границах. Что значит, что X >= x1 и X >= x2? Это значит, что X больше обоих чисел x1 и x2. Это можно записать одним неравнеством - X больше максимума из двух чисел:
max(x1, x2) <= X

Так же и по правым границам:
X <= min(x1 + w1, x2 + w2)

В итоге:
max(x1, x2) <= X <= min(x1 + w1, x2 + w2)

Эти неравенства имеют решение, если левая граница не превосходит правой:
max(x1, x2) <= min(x1 + w1, x2 + w2)

Вот у вас условие, что по оси OX есть хоть одна точка пересечения. Если вам касающиеся квадраты не надо считать пересекающимеся, то замените знак <= на строгое неравенство.

Точно также проверьте, что есть пересечение по OY. Если пересечение есть и там и там, то квадраты пересекаются. Т.е. весь ваш код должен найти 2 минимума, 2 максимума, сделать 2 сравнения и соединить их через логичиское И.
Ответ написан
Griboks
@Griboks
Для разнообразия: расстояние между центрами квадратов меньше суммы радиусов вписанных окружностей.
Ответ написан
TMProject
@TMProject
Frontend developer React/Redux
Для определения коллизии между двумя квадратами можно использовать простой алгоритм:

Определить границы каждого квадрата, то есть вычислить координаты левого верхнего угла и правого нижнего угла для каждого квадрата.
Проверить, пересекаются ли границы квадратов по осям X и Y. Если пересекаются, значит квадраты могут столкнуться.
Для проверки столкновения на самом деле нам нужно убедиться, что оба квадрата пересекаются на самом деле, а не только их границы. Для этого нужно проверить, есть ли пересечение между сторонами квадратов.
Вот пример функции на JavaScript, которая реализует этот алгоритм:
function detectCollision(sq1, sq2) {
  // вычисляем границы квадратов
  const sq1_left = sq1.x;
  const sq1_right = sq1.x + sq1.side;
  const sq1_top = sq1.y;
  const sq1_bottom = sq1.y + sq1.side;
  
  const sq2_left = sq2.x;
  const sq2_right = sq2.x + sq2.side;
  const sq2_top = sq2.y;
  const sq2_bottom = sq2.y + sq2.side;
  
  // проверяем, пересекаются ли границы квадратов по осям X и Y
  const x_collide = sq1_right >= sq2_left && sq1_left <= sq2_right;
  const y_collide = sq1_bottom >= sq2_top && sq1_top <= sq2_bottom;
  
  // если пересекаются, проверяем наличие пересечения сторон
  if (x_collide && y_collide) {
    const top_collision = sq1_bottom >= sq2_top && sq1_top <= sq2_top;
    const bottom_collision = sq1_top <= sq2_bottom && sq1_bottom >= sq2_bottom;
    const left_collision = sq1_right >= sq2_left && sq1_left <= sq2_left;
    const right_collision = sq1_left <= sq2_right && sq1_right >= sq2_right;
    
    return top_collision || bottom_collision || left_collision || right_collision;
  }
  
  return false;
}


Здесь sq1 и sq2 представляют объекты квадратов со следующими свойствами:
const square = {
  x: 100, // координата левого верхнего угла по оси X
  y: 50, // координата левого верхнего угла по оси Y
  side: 30 // длина стороны квадрата
};


Эта функция возвращает true, если квадраты пересекаются, и false в противном случае
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы