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

Създадох тази функция, за да мога да проверя дали два обекта се докосват в модел на сблъсък на 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 в противен случай.

Тествайте тази функция, като й предоставите няколко тестови случая. Ако не можете да визуализирате в главата си, начертайте 2D мрежа и маркирайте осите, след което нарисувайте произволни правоъгълници. Изберете две, които не се припокриват, дайте ги на вашата функция и проверете дали връща 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