Столкновение AABB удваивает размер фактического спрайта - PullRequest
0 голосов
/ 31 августа 2018

Итак, этот код работал для коллизии AABB, пока я не решил сделать спрайт больше по оси Y, чем по оси X. Я пытался исправить код, но теперь он просто удваивает размер столкновения, чем фактический размер спрайта. ех. размер спрайта 1 iVec2 (50 100), размер спрайта 2 iVec2 (30,30).

CollisionData Collision::DoCollision(GameObject &object1, GameObject &object2) {

iVec2 center(object1.Position.x + object1.Size.x / 2, object1.Position.y + object1.Size.y / 2);

iVec2 half_extents(object2.Size.x / 2, object2.Size.y / 2);
iVec2 aabb_center(object2.Position.x + half_extents.x, object2.Position.y + half_extents.y);

iVec2 difference = center - aabb_center;
iVec2 difference2 = center - aabb_center;

iVec2 clamped = glm::clamp(difference, -half_extents, half_extents);
iVec2 clamped2 = glm::clamp(difference2, -iVec2(object1.Size.x / 2, object1.Size.y / 2), iVec2(object1.Size.x / 2, object1.Size.y / 2));

iVec2 closest = aabb_center + clamped;
iVec2 closest2 = aabb_center + clamped2;

difference = closest - center;
difference2 = closest2 - center;

if (glm::length(difference) <= object1.Size.x / 2 || glm::length(difference2) <= object1.Size.y / 2)
    return std::make_tuple(GL_TRUE, VectorDirection(difference), difference);
else return std::make_tuple(GL_FALSE, UP, glm::vec2(0, 0));

}

1 Ответ

0 голосов
/ 31 августа 2018

Рекомендую сделать простую проверку перекрытия.

Если 2 сегмента перекрываются, можно проверить:

overlap = (x1+w1) > x2 && (x2+w2) > x1

, где x1 - начало, а w1 - ширина первого сегмента. x2 - это начало, а w2 - ширина сегмента 2n.

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

bool overlap = 
    (object1.Position.x + object1.Size.x) > object2.Position.x) &&
    (object2.Position.x + object2.Size.x) > object1.Position.x) &&
    (object1.Position.y + object1.Size.y) > object2.Position.y) &&
    (object2.Position.y + object2.Size.y) > object1.Position.y);

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

CollisionData Collision::DoCollision(GameObject &object1, GameObject &object2) {

    iVec2 center1(
        object1.Position.x + object1.Size.x / 2,
        object1.Position.y + object1.Size.y / 2);
    iVec2 center2(
        object2.Position.x + object2.Size.x / 2,
         object2.Position.y + object2.Size.y / 2);

    iVec2 dist = center1 - center2;
    iVec2 size((object1.Size.x + object2.Size.x) / 2, (object1.Size.y + object2.Size.y) / 2);


    iVec2 difference = size - iVec2(abs(dist.x), abs(dist.y));

    bool overlap = difference.x > 0 && difference.y > 0;

    if ( overlap )
    {
        iVec2 min1 = object1.Position;
        iVec2 min2 = object2.Position;
        iVec2 max1 = object1.Position + object1.Size;
        iVec2 max2 = object2.Position + object2.Size;

        bool horizontal = difference.x > difference.y;
        if ( min2.x > min1.x && max1.x < max2.x || min1.x > min2.x && max2.x < max1.x )
             horizontal = false;
        else if ( min2.y > min1.y && max1.y < max2.y || min1.y > min2.y && max2.y < max1.y )
             horizontal = true;

        return std::make_tuple(
            GL_TRUE, !horizontal ? (dist.x < 0 ? LEFT: RIGHT) : (dist.y < 0 ? UP : DOWN), difference );
    }

    return std::make_tuple(GL_FALSE, UP, glm::vec2(0, 0));
}
...