Функция обнаружения столкновений

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

function hitTest(x1, y1, w1, h1, x2, y2, w2, h2) {
    //x1, y1 = x and y coordinates of object 1 
    for (var x = 0; x < AliLength; x++) {
        x1 = AliensArrR1[x].getX();
        y1 = AliensArrR1[x].getY();
    }
    //w1, h1 = width and height of object 1
    w1 = 50;
    h1 = 18;
    //x2, y2 = x and y coordinates of object 2 (usually midpt)
    for (var x = 0; x < bullets.length; x++) {
        x2 = bullets[x].getX();
        y2 = bullets[x].getX();
    }
    // w2, h2 = width and height of object 2
    w2 = 3;
    h2 = 13;
    if ((x1 <= x2 && x1 + w1 >= x2) &&
    (y1 <= y2 && y1 + h1 >= y2) && (x2 <= x1 && x2 + w2) && (y2 <= y2 && y2 + h2))
        alert("Hit");
    else
        return false;
};

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

Любые предложения очень ценятся!

редактировать: я пытаюсь проверить, перекрывается ли когда-либо один объект шириной 18 и 50 с моим другим объектом шириной 3 и высотой 13. Они никогда не меняют только изменение осей x и y. Я новичок в обнаружении столкновений и после пары попыток применить логику проверки x и y на каждом, чтобы увидеть, пересекаются ли они. Я думал, что попрошу помощи, так как явно иду в неправильном направлении.

![Это то, чего я пытаюсь добиться]:http://uploads.gamedev.net/monthly_06_2011/ccs-8549-0-64600400-1307074262.gif


person li x    schedule 11.04.2014    source источник
comment
Вы слишком часто используете заглавные буквы в качестве начальных букв, даже в пределах alert(). В JS только имена функций-конструкторов должны начинаться с заглавной буквы.   -  person Teemu    schedule 12.04.2014
comment
Я добавил предупреждение после вставки из моей IDE, но согласился с другого языка, я все еще привыкаю к ​​правильному синтаксису. Меня это раздражает так же, как и вас :)!   -  person li x    schedule 12.04.2014
comment
Что ж, я не возражаю против вашего соглашения, только что упомянутого, но Alert() выдаст вам справочную ошибку...   -  person Teemu    schedule 12.04.2014
comment
Обновил тему, в моей версии такого не было.   -  person li x    schedule 12.04.2014
comment
Я не понимаю, почему вы получаете аргументы и ничего с ними не делаете. Также обратите внимание, что после циклов for значения x1 и y1 будут последним элементом в массиве ali, то же самое относится к циклу x2 y2.   -  person Tom Roggero    schedule 12.04.2014
comment
Вам действительно нужно выбрать лучшие имена для переменных. Называя все x и y, даже переменные цикла, и просто добавляя к ним числа, даже небольшой код, подобный этому, может быть очень трудным для чтения.   -  person Ingo Bürk    schedule 12.04.2014
comment
Ваше состояние выглядит странно. Почему существует проверка для x1 <= x2 и x2 <= x1 и y2 <= y2? Что делает y2 + h2? Я предлагаю разбить ваши условия и уточнить, что они должны делать   -  person wongcode    schedule 12.04.2014
comment
Обновил мою исходную ветку с моим дополнительным разъяснением моих целей.   -  person li x    schedule 12.04.2014


Ответы (3)


Я предлагаю вам немного реорганизовать ваш код. Сохраните восемь аргументов, но ничего им не присваивайте в функции hitTest и не ссылайтесь ни на какие глобальные переменные или константы. Просто сравните заданные координаты и ширину и верните true, если они перекрываются, false в противном случае.

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

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

Подсказка

Если вам трудно выполнять проверку столкновений в 2D, создайте более простую функцию, которая берет два отрезка 1D-линии (x1, w1, x2, w2) и определяет, перекрываются ли они. Случай 2D можно разбить на две проверки 1D: объекты должны перекрываться как по горизонтали, так и по вертикали.

Окончательное решение

x1 + w1 >= x2 && x2 + w2 >= x1 && y1 + h1 >= y2 && y2 + h2 >= y1
person tom    schedule 11.04.2014
comment
Это был вызывающе тот ответ, который я искал, я собираюсь набросать это на доске и попробовать так ... надо было подумать об этом раньше! - person li x; 12.04.2014
comment
Я думаю, что большая причина того, почему я нахожу это более сложным, заключается в том, как я реализую изображения, на которых я хочу проверить столкновение. Добавляя их в массив, я не уверен, как получить значения положения в этот алгоритм без использования цикла for. - person li x; 12.04.2014
comment
Хитрость заключается в использовании вложенных циклов for: for (each alien) { for (each bullet) { if (hitTest(current alien and current bullet)) { ... } } } - person tom; 12.04.2014
comment
В настоящее время это то, что у меня есть ((x1 >= x2 + w1 && x2 <= x1 + w2) && (y1 >= y2 + w1 && y2 <= y1 + w2)) Кажется, не работает :/ - person li x; 12.04.2014
comment
Должно быть x1 + w1 >= x2 && x2 + w2 >= x1 (правый край одного сегмента должен быть правее левого края другого сегмента). То же самое для y. - person tom; 12.04.2014

В основном это сделано, но...

Учитывая w1 ширину, h1 высоту, x1 позицию X, y1 позицию Y объекта 1 и то же самое для x2, y2, w2, h2 объекта 2:

Условие должно быть ИЛИ между условиями, и я уверен, что в вашей вертикальной части есть несколько опечаток. Версия с комментариями:

if (
    // Horizontal collision
    // Does right edge of 1 collide with left edge of 2? Only when 1 to the left of 2
    (x1 <= x2 && x1 + w1 >= x2) ||
    // Does left edge of 1 collide with right edge of 2? Only when 2 to the left of 1
    (x2 <= x1 && x2 + w2 >= x1) ||

    // Vertical collision
    // Does bottom edge of 1 collide with top edge of 2? Only when 1 above 2
    (y1 <= y2 && y1 + h1 >= y2) ||
    // Does top edge of 1 collide with bottom edge of 2? Only when 2 above 1
    (y2 <= y1 && y2 + h2 >= y1)
) {
    // hit
}
person Tom Roggero    schedule 11.04.2014
comment
Этот код неверен. Проверьте это с помощью (x1, y1) = (0, 0), (x2, y2) = (10, 0), w1 = h1 = w2 = h2 = 4. Они не пересекаются, но написано, что они попали. - person tom; 12.04.2014

Это правильно, но так:

function hitTest(x1, y1, w1, h1, x2, y2, w2, h2) {    
  if (((x1 <= x2 && x1 + w1 >= x2) || (x2 <= x1 && x2 + w2 >= x1)) && ((y1 <= y2 && y1 + h1 >= y2) || (y2 <= y1 && y2 + h2 >= y1)))
    return true; 
  else
    return false;    
}
person MattX    schedule 30.01.2016