AABB 충돌로 인한 플랫폼 점프 문제


9

먼저 다이어그램을 참조하십시오.

AABB 물리 엔진이 교차점을 해석 할 때 관통이 작은 축을 찾아 해당 축의 엔티티를 "밀어 내기"하면됩니다.

"왼쪽으로 점프 이동"예를 고려하십시오.

  • velocityX가 velocityY보다 큰 경우 AABB는 엔티티를 Y 축으로 밀어내어 점프를 효과적으로 중지합니다 (결과 : 공중에서 멈춤).
  • velocityX가 속도보다 작 으면 (그림에 표시되지 않음) AABB가 엔티티를 X 축으로 밀어 내므로 프로그램이 의도 한대로 작동합니다.

이 문제를 어떻게 해결할 수 있습니까?

소스 코드:

public void Update()
{
    Position += Velocity;
    Velocity += World.Gravity;

    List<SSSPBody> toCheck = World.SpatialHash.GetNearbyItems(this);

    for (int i = 0; i < toCheck.Count; i++)
    {
        SSSPBody body = toCheck[i];
        body.Test.Color = Color.White;

        if (body != this && body.Static)
        {                   
            float left = (body.CornerMin.X - CornerMax.X);
            float right = (body.CornerMax.X - CornerMin.X);
            float top = (body.CornerMin.Y - CornerMax.Y);
            float bottom = (body.CornerMax.Y - CornerMin.Y);

            if (SSSPUtils.AABBIsOverlapping(this, body))
            {
                body.Test.Color = Color.Yellow;

                Vector2 overlapVector = SSSPUtils.AABBGetOverlapVector(left, right, top, bottom);

                Position += overlapVector;
            }

            if (SSSPUtils.AABBIsCollidingTop(this, body))
            {                      
                if ((Position.X >= body.CornerMin.X && Position.X <= body.CornerMax.X) &&
                    (Position.Y + Height/2f == body.Position.Y - body.Height/2f))
                {
                    body.Test.Color = Color.Red;
                    Velocity = new Vector2(Velocity.X, 0);

                }
            }
        }               
    }
}

public static bool AABBIsOverlapping(SSSPBody mBody1, SSSPBody mBody2)
{
    if(mBody1.CornerMax.X <= mBody2.CornerMin.X || mBody1.CornerMin.X >= mBody2.CornerMax.X)
        return false;
    if (mBody1.CornerMax.Y <= mBody2.CornerMin.Y || mBody1.CornerMin.Y >= mBody2.CornerMax.Y)
        return false;

    return true;
}
public static bool AABBIsColliding(SSSPBody mBody1, SSSPBody mBody2)
{
    if (mBody1.CornerMax.X < mBody2.CornerMin.X || mBody1.CornerMin.X > mBody2.CornerMax.X)
        return false;
    if (mBody1.CornerMax.Y < mBody2.CornerMin.Y || mBody1.CornerMin.Y > mBody2.CornerMax.Y)
        return false;

    return true;
}
public static bool AABBIsCollidingTop(SSSPBody mBody1, SSSPBody mBody2)
{
    if (mBody1.CornerMax.X < mBody2.CornerMin.X || mBody1.CornerMin.X > mBody2.CornerMax.X)
        return false;
    if (mBody1.CornerMax.Y < mBody2.CornerMin.Y || mBody1.CornerMin.Y > mBody2.CornerMax.Y)
        return false;

    if(mBody1.CornerMax.Y == mBody2.CornerMin.Y)
        return true;

    return false;
}
public static Vector2 AABBGetOverlapVector(float mLeft, float mRight, float mTop, float mBottom)
{
    Vector2 result = new Vector2(0, 0);

    if ((mLeft > 0 || mRight < 0) || (mTop > 0 || mBottom < 0))
        return result;

    if (Math.Abs(mLeft) < mRight)
        result.X = mLeft;
    else
        result.X = mRight;

    if (Math.Abs(mTop) < mBottom)
        result.Y = mTop;
    else
        result.Y = mBottom;

    if (Math.Abs(result.X) < Math.Abs(result.Y))
        result.Y = 0;
    else
        result.X = 0;

    return result;
}

답변:


2

방금 잘못된 위치를 증명하려고 시도하지 않은 코드를 보았습니다.

나는 코드를 보았고이 두 줄은 이상하게 보였다.

if ((Position.X >= body.CornerMin.X && Position.X <= body.CornerMax.X) &&
(Position.Y + Height/2f == body.Position.Y - body.Height/2f))

당신은 간격을 확인한 다음 이질을 확인합니까? 나는 틀릴 수도 있지만 (둥근 반올림이있을 수 있습니다) 문제가 발생할 수 있습니다.


0

다른 사람들의 코드를 읽기는 어렵지만 테스트 할 수는 없지만 이것이 가능한 (완전히 브레인 스토밍 된) 해결 방법이라고 생각합니다.

  1. 충돌 감지가 발생하기 전에 플레이어 속도를 임시 변수에 저장하십시오.
  2. 충돌 응답을 마친 후 플레이어 X 또는 Y 위치가 수정되었는지 확인하십시오
  3. X 위치가 변경된 경우 플레이어 Y 속도를 응답 이전의 속도로 수동으로 재설정합니다 ( "안전 재설정").

그런데 플레이어가 점프하는 동안 지붕에 닿으면 현재 코드는 어떻게됩니까?


속도는 충돌 응답의 영향을받지 않기 때문에 속도를 변경해도 아무 것도 해결되지 않습니다. 응답은 단순히 플레이어의 위치를 ​​변경하고 벨로 시티는 변경되지 않습니다. 플레이어가 지붕에 부딪히면 잠시 동안 뜬 다음 다시 내려옵니다. 천장에 닿을 때 Velocity를 0으로 설정하지 않았기 때문에 의도되었습니다.
— Vittorio Romeo

GetOverlapVector 메서드에서 결과 벡터 구성 요소 중 하나를 0으로 설정하는 코드를 제거하면 어떻게됩니까?
— TravisG

개체가 대각선으로 튀어 나와서 때로는 제대로 작동하지 않으며, 그렇지 않으면 그리드에있는 것처럼 스냅됩니다.
— Vittorio Romeo

지금은 이해할 수 없습니다. 엔티티가 푸시되는 방식은 충돌하는 바디와의 거리에 따라 달라 지지만 알고리즘은 이미 그렇게합니다. 내일 다시 한번 살펴 보겠습니다.
— TravisG
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.