Учебное пособие N по обнаружению столкновений, выпуклое/вогнутое

Я следую учебному пособию по игре N для обработки обнаружения столкновений для одной из моих игр, одна вещь, которая неясна в этом подходе, заключается в том, что они говорили о теореме об отдельной оси на этой странице, но если вы видите в реализации (учебник A), нет, где я мог видеть была обработана отдельная ось. В приведенном ниже URL-адресе раздел --= round shapes =-- рассказывает о том, как обрабатывать коллизии между AABB и выпуклыми/вогнутыми формами. http://www.metanetsoftware.com/technique/tutorialA.html#section2

У меня есть основная идея реализации векторов и отдельных осей, но не этот подход. Из этого урока я понял, что весь игровой мир N состоит из 5-8 различных форм (плиток), каждая плитка по очереди вращается по горизонтали/вертикали, что дает 4 комбинация, обращенная влево, вправо, вверху и внизу. Эта информация о лицевой стороне хранится в каждой плитке со знаком x, y.

obj - игрок (прямоугольник) t - плитка x,y - проекция ограничивающей рамки

Реализация. Может ли кто-нибудь объяснить, что именно делает этот код?

function ProjAABB_Concave(x,y,obj,t)
{       
    //if distance from "innermost" corner of AABB is further than tile radius,
    //collision is occuring and we need to project

    var signx = t.signx;
    var signy = t.signy;

    var ox = (t.pos.x + (signx*t.xw)) - (obj.pos.x - (signx*obj.xw));//(ox,oy) is the vector form the innermost AABB corner to the
    var oy = (t.pos.y + (signy*t.yw))- (obj.pos.y - (signy*obj.yw));//circle's center

    var twid = t.xw*2;
    var rad = Math.sqrt(twid*twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
                                        //note that this should be precomputed at compile-time since it's constant

    var len = Math.sqrt(ox*ox + oy*oy);
    var pen = len - rad;
    if(0 < pen)
    {
        //collision; we need to either project along the axes, or project along corner->circlecenter vector

        var lenP = Math.sqrt(x*x + y*y);
        if(lenP < pen)
        {
            //it's shorter to move along axis directions
            obj.ReportCollisionVsWorld(x,y,x/lenP, y/lenP, t);

            return COL_AXIS;
        }
        else
        {
            //project along corner->circle vector
            ox /= len;//len should never be 0, since if it IS 0, rad should be > than len
            oy /= len;//and we should never reach here

            obj.ReportCollisionVsWorld(ox*pen, oy*pen, ox, oy, t);

            return COL_OTHER;
        }

    }

    return COL_NONE;

}

person Sabha B    schedule 20.06.2011    source источник
comment
ну, это явно очень, очень плохой код коллизий. Вычислять Math.sqrt как для len, так и для rad, а затем для lenP совершенно глупо: сравнивать непосредственно КВАДРАТ суммы. Это обнаружение столкновений в игре 101. Действительно.   -  person SyntaxT3rr0r    schedule 20.06.2011
comment
@SyntaxT3rr0r: Я понял вас, но если вы видите, что скорость / плавность этой игры довольно высока из-за этой предварительно рассчитанной математики, вот почему у меня возник соблазн пройти этот урок. Однако не могли бы вы предложить какой-либо учебник по обработке столкновений между AABB и выпуклыми/вогнутыми. Помимо следования этому руководству, я реализовал обнаружение столкновений на основе отдельных осей, но оно работает только для выпуклых форм, а не для закругленных форм.   -  person Sabha B    schedule 20.06.2011


Ответы (2)


Это простое столкновение сферы со сферой. Смотрите часть, где они делают

var pen = len - rad;
if(0 < pen)

Они просто проверяют, что радиус объекта "t" за вычетом текущего радиуса объекта касается (=0) или пересекает (‹0).

Часть, где они делают

var ox = (t.pos.x + (signx*t.xw)) - (obj.pos.x - (signx*obj.xw));//(ox,oy) is the vector form the innermost AABB corner to the
var oy = (t.pos.y + (signy*t.yw))- (obj.pos.y - (signy*obj.yw));//circle's center

Они перемещают объект «t» в систему отсчета «obj».

person Chiguireitor    schedule 20.06.2011
comment
@ SyntaxT3rr0r: это учебник, не нужно указывать на его подводные камни (в конечном итоге Ананд, вероятно, обнаружит, что может использовать квадраты радиусов). - person Chiguireitor; 20.06.2011
comment
Если они проверяют радиус (расстояние между центрами двух объектов == суммарный радиус двух объектов), мой вопрос заключается в том, как можно использовать этот подход для обнаружения столкновения между односторонней изогнутой формой, см. Рисунок 6. - person Sabha B; 20.06.2011
comment
Они сталкиваются с обоими объектами, как если бы они были двумя сферами. Прямоугольная сфера - это воображаемая сфера от центра к углу, если есть пересечение обеих сфер, они проверяют, что расстояние между углом прямоугольника и вогнутым радиусом достаточно близко, чтобы столкнуться. Чтобы исключить угол вогнутого объекта, если радиус сферы прямоугольника равен › len, то len - rad будет меньше 0 и коллизии не будет :) - person Chiguireitor; 21.06.2011
comment
теперь я понял код вместе с вашим описанием, теперь мне любопытно узнать, что не так с этим кодом столкновения. Еще один вопрос: как выполнить обнаружение столкновений на изогнутой поверхности (например, в игре Locoroco)? - person Sabha B; 21.06.2011
comment
@Anandh: Плохие стороны этого кода: 1) широкое использование Math.sqrt, вы можете использовать все в квадрате и вуаля; и 2) signx*obj.xw вы можете использовать условное изменение знака в локальной переменной, менее затратное, чем умножение. Примите во внимание, что эти плохие вещи плохи только в том случае, если вы используете этот код для столкновения тысяч объектов или если ваш код будет работать на мобильной платформе (вычислительная мощность быстрее разряжает батарею). - person Chiguireitor; 21.06.2011

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

person Open the way    schedule 20.06.2011