2009-02-18 4 views
6

Я еще не отмечал этот вопрос.
В настоящее время принят ответ был принят автоматически из-за Bounty Time-Limit
WPF: Поиск элемента вдоль пути


Со ссылкой на this programming game я в настоящее время здание.

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


Теперь мне нужен способ, чтобы обнаружить, если робот обнаружил еще один робот в определенном угле (в зависимости от того, где турель может столкнуться):

alt text http://img21.imageshack.us/img21/7839/robotdetectionrg5.jpg

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

Боты - это просто холсты, которые постоянно переводятся на Battle Arena (другой холст).

Я знаю заголовок башни (то, как она будет в настоящее время обращена), и с этим мне нужно найти, есть ли какие-либо боты на своем пути (и путь должен быть определен в виде «точки зрения» , изображенный на рисунке выше, в виде красного треугольника. Надеюсь, что изображение упростит то, что я пытаюсь передать.

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


[UPDATE]

Я пробовал вычисления, которые вы мне сказали, но это не работает должным образом, поскольку, как вы можете видеть из изображения, bot1 не должен видеть Bot2. Вот пример:

alt text http://img12.imageshack.us/img12/7416/examplebattle2.png

В приведенном выше сценарии Bot 1 проверяет, может ли он видеть Bot 2. Вот детали (по Waylon Flinn's answer):

angleOfSight = 0.69813170079773179 //in radians (40 degrees) 
orientation = 3.3 //Bot1's current heading (191 degrees) 

x1 = 518 //Bot1's Center X 
y1 = 277 //Bot1's Center Y 

x2 = 276 //Bot2's Center X 
y2 = 308 //Bot2's Center Y 

cx = x2 - x1 = 276 - 518 = -242 
cy = y2 - y1 = 308 - 277 = 31 

azimuth = Math.Atan2(cy, cx) = 3.0141873380511295 

canHit = (azimuth < orientation + angleOfSight/2) && (azimuth > orientation - angleOfSight/2) 
     = (3.0141873380511295 < 3.3 + 0.349065850398865895) && (3.0141873380511295 > 3.3 - 0.349065850398865895) 
     = true 

Согласно выше вычислений, Bot1 может видеть Bot2, но, как вы можете видеть из изображения, это невозможно, так как они обращены в разные стороны.

Что я делаю неправильно в приведенных выше расчетах?

+0

Является ли это чисто двумерной проблемой или является вашим рисунком 2D-представление проблемы 3D? – DJClayworth

+0

Нет, это просто 2D-платформа. –

+0

Aw чувак. Это зависит от того, к чему вы относитесь. Для того, чтобы приведенный выше код работал, ориентация должна быть относительно горизонтального вектора (1,0), иначе вы получите результаты, как вы получаете выше. Это просто вопрос добавления или вычитания PI/2 в вашу текущую ориентацию. –

ответ

3

Угол между роботами - arctan (x-distance, y-distance) (большинство платформ предоставляют этот 2-аргумент arctan, который регулирует угол для вас. Затем вам просто нужно проверить, меньше ли этот угол меньше номер от текущего заголовка.

EDIT: извините за расплывчатый ответ, но вот некоторые из моих заметок на обновлении:

  • координаты будет в декартовой системе, а не системы окна. Это приводит к некоторым различным номерам

    Ориентация: 3.3 < - это неверно, bot1 похоже, что он ориентирован примерно на 4 или что-то в этом роде. 191 градус будет около 8:30 позиции на часах, что почти прямо указано в танке 2. Неудивительно, что система возвращает «Видимый»!

    азимут: су будет -31 (31 единиц в рамках), а не 31.

С этими изменениями, вы должны получить правильные результаты.

+0

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

+0

Этот ответ получил Автопринятие из-за Bounty Time-Limit –

+0

@AndreasGrech вы можете его не принимать. –

1

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

Единственная сложная вещь будет обработка краевого случая, когда угол идет от 2PI радианов 0.

0

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

Лучший совет, который я получил за высокие оценки, делаю что-то очень простое, не разделяй, чтобы доставить что-то блестящее.

+0

Это хороший совет. Обнаружение столкновений с использованием кругов легко и точно для первого разреза. – geofftnz

0

Действительно ли у вашей башни такой широкий шаблон стрельбы? Путь, пройденный пулей, будет прямой линией, и она не станет больше по мере ее перемещения. У вас должен быть простой вектор в направлении башни, представляющей зону уничтожения башен. Каждый танк будет иметь ограниченный круг, представляющий их уязвимую область. Затем вы можете продолжить работу с трассировкой лучей. Простой пересечение луча/окружности. Посмотрите раздел 3 документа Intersection of Linear and Circular Components in 2D.

+0

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

+0

его названный вид усечения. стандартный графический алгоритм для определения того, какие элементы рисовать в 3d-сцене. вы хотите знать, находится ли объект в виде усечения с определенной точки зрения. Я буду искать ссылки. –

1

Что-то вроде этого в классе вашего бота (C# код):

/// <summary> 
/// Check to see if another bot is visible from this bot's point of view. 
/// </summary> 
/// <param name="other">The other bot to look for.</param> 
/// <returns>True iff <paramref name="other"/> is visible for this bot with the current turret angle.</returns> 
private bool Sees(Bot other) 
{ 
    // Get the actual angle of the tangent between the bots. 
    var actualAngle = Math.Atan2(this.X - other.X, this.Y - other.Y) * 180/Math.PI + 360; 

    // Compare that angle to a the turret angle +/- the field of vision. 
    var minVisibleAngle = (actualAngle - (FOV_ANGLE/2) + 360); 
    var maxVisibleAngle = (actualAngle + (FOV_ANGLE/2) + 360); 
    if (this.TurretAngle >= minVisibleAngle && this.TurretAngle <= maxVisibleAngle) 
    { 
     return true; 
    } 
    return false; 
} 

Примечания:

  • В + 360 есть, чтобы заставить любые отрицательные углы их соответствующих положительных значений и переложить граничный случай угла 0, чтобы где-то легче провести тест диапазона.
  • Это может быть выполнимо с использованием только радианских углов, но я думаю, что они грязные и трудночитаемые:/
  • Для получения более подробной информации см. Документацию Math.Atan2.
  • Я настоятельно рекомендую заглянуть в XNA Framework, так как он создан с учетом дизайна игры. Однако он не использует WPF.

Это предполагает, что:

  • нет никаких препятствий, чтобы заслонять вид
  • Bot класс имеет X и Y свойства
  • Х и Y свойства находятся в центре бота.
  • Класс бота - свойство TurretAngle, которое обозначает положительный угол башни относительно оси x, против часовой стрелки.
  • Класс бота имеет статический угол const под названием FOV_ANGLE, обозначающий поле зрения башни.

Отказ от ответственности: Это не тестируются и даже проверил компилировать, адаптировать ее по мере необходимости.

+0

minVisibleAngle (и max) всегда вычисляются прибл. более 600, но TurretAngle> = 0 и <360, поэтому условие, что TurretAngle больше, чем minVisibleAngle, никогда не может вернуть true. Что я делаю не так ? –

+0

Кстати, что касается FOV_ANGLE, я жестко кодирую 40 атм. Это слишком много, слишком мало, или это хорошо? –

+0

Поле зрения в типичных шутерах первого лица составляет 45-90 градусов. Поле зрения человека составляет около 200 градусов, чтобы дать вам справочную систему. –

1

Несколько предложений после реализации что-то подобное (давно!):

Далее предполагается, что вы пробегаем по всем роботам на поле боя (не особенно приятно практике, но быстро и легко получить что-то работает!)

1) Его намного проще проверить, находится ли бот в зоне действия, если он в настоящее время может быть замечен в пределах FOV, например

int range = Math.sqrt(Math.abs(my.Location.X - bots.Location.X)^2 + 
      Math.abs(my.Location.Y - bots.Location.Y)^2); 

if (range < maxRange) 
{ 
    // check for FOV 
} 

Это гарантирует, что он может потенциально короткий cuircuit много FOV проверки и ускорить процесс запуска моделирования. В качестве предостережения у вас может быть некоторая случайность, чтобы сделать ее более интересной, так что на определенном расстоянии вероятность увидеть линейно пропорциональна диапазону бота.

2) This article Кажется, что на нем есть расчетные данные FOV.

3) Как выпускник ИИ ... Ней вы попробовали Neural Networks, вы могли обучить их распознавать, находится ли робот в радиусе действия и действительная цель. Это отрицало бы любую ужасно сложную и запутанную математику! У вас может быть многослойный персептрон [1], [2] подача в координатах ботов, а цели - сильные и получающие хорошее решение огня/без огня в конце. ПРЕДУПРЕЖДЕНИЕ: Я чувствую себя обязанным сказать вам, что эта методология не является самой простой задачей и может быть ужасно расстраивающей, когда она идет не так. Из-за (simle) недетерминированного характера этой формы алгоритма отладка может быть болью. Кроме того, вам понадобится какая-то форма обучения либо Back Propogation (с учебными примерами), либо Genetic Algorithm (еще один сложный процесс для совершенства)! Учитывая выбор, я бы использовал номер 3, но его нет для всех!

1

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

/// assumming canvas1 is firing on canvas2 

// positions of canvas1 and canvas2, respectively 
// (you're probably tracking these in your Tank objects) 
int x1, y1, x2, y2; 

// orientation of canvas1 (angle) 
// (you're probably tracking this in your Tank objects, too) 
double orientation; 
// angle available for firing 
// (ditto, Tank object) 
double angleOfSight; 

// vector from canvas1 to canvas2 
int cx, cy; 
// angle of vector between canvas1 and canvas2 
double azimuth; 
// can canvas1 hit the center of canvas2? 
bool canHit; 

// find the vector from canvas1 to canvas2 
cx = x2 - x1; 
cy = y2 - y1; 

// calculate the angle of the vector 
azimuth = Math.Atan2(cy, cx); 
// correct for Atan range (-pi, pi) 
if(azimuth < 0) azimuth += 2*Math.PI; 

// determine if canvas1 can hit canvas2 
// can eliminate the and (&&) with Math.Abs but this seems more instructive 
canHit = (azimuth < orientation + angleOfSight) && 
    (azimuth > orientation - angleOfSight); 
+0

. Я разместил некоторые вычисления в своем сообщении ([ОБНОВЛЕНИЕ]). Не могли бы вы проверить их? Благодарю. –

1

Этого можно легко достичь с помощью концепции в векторной математике, называемой точечным продуктом.

http://en.wikipedia.org/wiki/Dot_product

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

(ПРИМЕЧАНИЕ. Если что-то не понятно, спрашивайте в комментариях, и я заполнит недостающие звенья)

Шаги:

1) Вам нужно два вектора, один заголовок вектор основного резервуара. Другой вектор, который вам нужен, получен из положения рассматриваемого резервуара и основного резервуара.

Для нашего обсуждения предположим, что вектор направления для основного резервуара (ax, ay) и вектор между положением основного резервуара и резервуаром-мишенью (bx, by). Например, если основной резервуар находится в месте (20, 30), а танк-мишень находится на (45, 62), тогда вектор b = (45-20, 62-30) = (25, 32).

Опять же, для обсуждения, давайте предположим, что заголовок основного резервуара (3,4).

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

2) Dot продукт определяется как

а * Ь = | || Ь | cos (угол)

прочитано как (продукт точки) b, так как a и b не являются числами, они являются векторами.

3) или выражены другим способом (после некоторой алгебраической манипуляции):

угол = Acos ((A * B)/| а || Ь |)

угол представляет собой угол между двумя векторами a и b, так что только эта информация может рассказать вам, может ли один танк видеть другого или нет.

| a | - величина вектора а, которая, согласно теореме Пифагора, равна просто sqrt (ax * ax + ay * ay), то же самое относится к | b |.

Теперь встает вопрос, как вы узнаете * b (точечный продукт b), чтобы найти угол.

4) Наступает помощь. Оказывается, что скалярное произведение также может быть выражен, как показано ниже:

а * Ь = ах * Вх + у * по

So угол = ACOS (ах * (BX + ау *) от/| A || b |)

Если угол меньше половины вашего FOV, то рассматриваемый резервуар находится в поле зрения. В противном случае это не так.

Таким образом, используя номера примеров выше:

На нашем примере чисел:

а = (3, 4) Ь = (25, 32)

| A | = sqrt (3 * 3 + 4 * 4)

| b | = SQRT (25 * 25 + 32 * 32)

угла = экос ((20 * 25 + 30 * 32)/| а || Ь |

(Обязательно, чтобы преобразовать результирующий угол до степени или радиан в зависимости от обстоятельств, прежде чем сравнивать его к FOV)

+0

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

+0

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

+0

Согласен, этот код, скорее всего, быстрее. Проблема в том, что математический новичок трудно понять. Моя мысль об обратном косинусе заключается в том, что вы можете удалить его, взяв косинус FOV/2 один раз, вне цикла. Вы также можете убедиться, что «a» является единичным вектором и сохраняет умножение. –

0

Обновленное проблема, кажется, из разных «нулевых» направлений orientation и azimuth: orientation 0, кажется, означает «прямо», но azimuth 0 «прямой right ".

Смежные вопросы