// личный канал‑лог
gavrilovlog
← все записи

Я сейчас испытываю какой-то небывалый восторг от разработки этого проекта. Да,…

👁 3561💬 1
Мое высшие образование “Инженер-конструктор”. Я провел 5,5 лет делая чертежи и разрабатывая различные 3D модели в таких программах как Компанс-3D и Autodesk Inventor. Большая часть задач как раз было на знания геометрии, в том числе умение определять пересечения объектов в декартовых координатах. А сопромат и баллистика это вообще был улет 🙂 Наверное поэтому мне сейчас интересно заниматься этим проектом. Так вот, то что я показал в прошлом посте, этот формат игр называется тайловый или его называют еще плиточный. Это означает, что игра состоит из множества квадратных или прямоугольных, а иногда даже шестиугольных элементов, называемых тайлами (tiles). Каждый такой тайл представляет собой маленький кусочек общего мира игры, будь то участок земли, часть здания, элемент ландшафта или другой объект. Так вот представим, что у нас есть какое-то взаимодействие между двумя объектами тайловой игры. Наш Player и например Coin(монетка), при пересечении этих двух объектов, должен случится какой-то эффект, в нашем случае это увеличение счета игрока `score`, а также исчезновение самой монетки с карты. Прелесть тайловых игр состоит в том, что для определения пересечения этих двух объектов, нам нужно определить пересекаются ли эти 2 плитки на координатной плоскости и это сделать очень просто, с помощью метода называемого AA-BB-Collision (Axis-Aligned Bounding Box). Как это работает: Предположим у нас есть 2 объекта и мы знаем где находятся центры этих объектов по X и по Y. Также нам известны высота и ширина плитки. Нам нужно определить левую и правую границу по оси X у каждого объекта и также верхнюю и нижнюю границу по оси Y. Это сделать очень просто. Напишем простую функцию для этого на TypeScript:

function calculateBounds(
  centerX: number,
  centerY: number,
  width: number,
  height: number,
): { left: number; right: number; top: number; bottom: number } {
  const halfWidth = width / 2;
  const halfHeight = height / 2;

  return {
    left: centerX - halfWidth,
    right: centerX + halfWidth,
    top: centerY - halfHeight,
    bottom: centerY + halfHeight,
  };
}
А теперь, чтобы определить, что наши объекты пересекаются, нам надо применить следующее условие: 1. Если левая граница первого объекта находится левее правой границы второго объекта и при этом правая граница первого объекта находится правее левой границы второго объекта, тогда по оси X есть пересечении, но нам нужно проверить еще и пересечении по оси Y. Добавим это к условию: Если верхняя граница первого объекта находится выше нижней границы второго объекта и при этом нижняя граница первого объекта находится ниже верхней границы второго объекта, тогда наши прямоугольники пересекаются. И вот как это выглядит в коде:

function isAABBCollision(
  object1: { left: number, right: number, top: number, bottom: number },
  object2: { left: number, right: number, top: number, bottom: number },
): boolean {
  return object1.left < object2.right &&
    object1.right > object2.left &&
    object1.top < object2.bottom &&
    object1.bottom > object2.top;
}
А чтобы добавить взаимодействие в тайловой игре, нужно проверять это условие для нашего объекта игрока с каждым объектом в отображаемой карте на каждом кадре. То есть если у нас игра имеет частоту 60 кадров в секунду и на карте имеется 10 объектов, то такая проверка должна осуществляться 60 раз в секунду с каждым из 10 объектов. Однако можно добавить некоторые хитрости, чтобы уменьшить количество таких проверок. А именно зная траекторию движения игрока, мы можем брать в расчет только те объекты, которые находятся на этой траектории или например если наши объекты статичны, тогда мы можем проверять только тот объект в ячейке которого находится наш игрок в данном кадре. И так далее. Результат на видео. От вас 👍 !💬 Telegram | !📹 Youtube
91

Комментарии · 1

  • @gavrilovlog
    Какой-то глюк телеграма на macOs. С телефона норм отображает, а тут такая дичь 🤷