HTML5 Canvas: обнаружение столкновения мыши и полигона - PullRequest
7 голосов
/ 01 сентября 2010

Итак, я делаю игру Tower Defense с HTML5 и Javascript. Моя единственная проблема - обнаружение, когда мышь вступает в контакт с путем атакующего, что необходимо для того, чтобы помешать игроку строить башни на пути. Путь злоумышленников определяется в файле MAP.js (см. Ссылку внизу) двухмерным массивом (массивом, содержащим пары x и y), поэтому мне нужно работать с рядом точек, которые составьте путь при подключении. Я просто хочу запретить игроку размещать башни, скажем, в 50 пикселях пути. Честно говоря, я просто ужасен в обнаружении столкновений, поэтому некоторая помощь будет принята с благодарностью.

Вот ссылка на весь код: http://shapeshifting.comuv.com/Tower_Defense/td/

Как вы можете себе представить, применимы только файлы .js, но большая часть соответствующего кода находится внутри файла objects.js. (Прошу прощения за беспорядок)

Ответы [ 3 ]

4 голосов
/ 27 января 2011

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

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

Если ваша карта представляет собой сетку, то у вас есть ответ - карта столкновений представляет собой предварительно рассчитанный 2D-массив - в основном очень маленькое черно-белое изображение с пикселем для каждого места в сетке. Белые пиксели (1) можно разместить, а черные (0) - нет. Вы просто используете этот двумерный массив true / false в качестве поиска. Если вы хотите сэкономить память, вы можете объединить каждую полосу из 32 пробелов в сетке в один битовый флаг.

Если ваша карта не является сеткой, то вы все равно хотите пересчитать вещи, но стратегия немного сложнее. Первая возможность состоит в том, чтобы выполнить математику, подобную Hitesh, чтобы получить карту столкновений с немного более высоким разрешением, а затем все остальное точно как стратегия сетки - так, например, если каждый блок пикселей 4x4 был одним входом столкновения, то может ли быть башня поместил - тест на то, чтобы его координаты были проверены, чтобы быть на вершине достаточно 1-ых - Вы могли бы требовать, чтобы 100% тестов были 1-ыми, или Вы могли бы позволить им достигнуть немного и позволить 75% тестов быть 1-ыми.

Если это все еще не достаточно подробно, вы можете выполнить эти более сложные тесты полигонов, но вы хотите, чтобы они были максимально простыми. Если не использовать предварительно рассчитанную сетку, самый простой двухмерный тест на столкновение - это 2 круга - вы просто рассчитываете расстояние между их центрами и проверяете, больше или меньше его сумма радиусов. Если вы пересчитаете свой путь монстра в след из кругов, следующий шаг - разделить эти круги на ... угадайте, что ... сетка. Это предотвращает каждую проверку от проверки каждого круга на карте. Это позволяет вам иметь большое количество таких кругов на карте столкновений, поскольку тест столкновения - это сначала поиск элементов сетки, над которыми в данный момент находится башня, а затем проверка, сталкивается ли она только с теми кругами, к которым она ближе всего, чем вся карта. Важно отметить, что эта предварительно рассчитанная сетка списков кругов часто будет иметь один и тот же круг в нескольких соседних элементах сетки, поскольку каждая запись в сетке, которая содержит любую часть данного круга, должна иметь этот круг в контрольном списке столкновения.

Одна из приятных вещей в первых двух подходах к сетке заключается в том, что очень легко выполнить QA самостоятельно - буквально сохраните карту столкновений в виде изображения и визуально осмотрите ее, чтобы убедиться, что она выглядит правильно для карты, на которой она основана. Вы также можете нарисовать его вручную, если не хотите писать код для их генерации.

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

Удачи!

2 голосов
/ 09 января 2011

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

Как проверить, находится ли точка внутри выпуклого многоугольника в двумерных целочисленных координатах?

Разложение на треугольники делает тест еще проще

2 голосов
/ 01 сентября 2010

Я бы подошел к этому поэтапно. Давайте посмотрим, с чего вы начнете. У вас есть путь, определенный точками - пары точек определяют отрезок. Так что у вас есть путь из отрезков. Когда пользователь перемещает мышь, вы получите координаты x, y текущей позиции. То, что вы хотите сделать, это найти расстояние от точки мыши до всех отрезков. Если он меньше 50 пикселей от любого отрезка, то вы не хотите, чтобы они там создавались.

Чтобы найти расстояние между точкой и отрезком, псевдокод выглядит следующим образом. Предположим, что точки A и B представляют оба конца отрезка, а точка C - это точка мыши.

float distancePoint2LineSegment(Point a, Point b, Point c) {
  Vector ab = b - a
  Vector ac = c - a
  Vector bc = c - b

  float e = dotProduct(ac, ab)
  if (e <= 0.0)
    return sqrt(dotProduct(ac, ac))

  float f = dotProduct(ab, ab)
  if (e >= f)
    return sqrt(dotProduct(bc, bc))

  return sqrt(dotProduct(ac, ac) - e * e / f)
}

Это ответило бы на ваш вопрос по обнаружению столкновений, но я думаю, что вы захотите посмотреть на производительность. Сколько отрезков линии будет на вашем пути, и вы хотите рассчитывать расстояние до каждого отрезка линии каждый раз, когда пользователь перемещает свою мышь? Вы можете поместить линейные сегменты в квадродерево так, чтобы вам приходилось только проверять столкновения точек мыши с меньшим количеством линейных сегментов.

...