AABB çarpışmalarında platform atlama sorunları


9

İlk önce şemaya bakın:

AABB fizik motorum bir kavşağı çözdüğünde, penetrasyonun daha küçük olduğu ekseni bularak objeyi o eksen üzerindeki "dışarı iterek" yapar.

"Atlayarak sola atlamak" örneği göz önüne alındığında:

  • Eğer hız X hız Y'den büyükse, AABB varlığı Y eksenine iterek atlamayı etkin bir şekilde durdurur (sonuç: oyuncu havada durur).
  • Hız X hızdan (şemada gösterilmemiştir) küçükse, program istendiği gibi çalışır, çünkü AABB varlığı X ekseninde iter.

Bu sorunu nasıl çözebilirim?

Kaynak kodu:

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;
}

Yanıtlar:


2

Ben sadece nerede yanlış olduğunu kanıtlamak için çalışmadım kodu baktı.

Ben koda baktım ve bu 2 satır garip görünüyordu:

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

Aralığı kontrol ettiniz ve sonra euquality mi kontrol ediyorsunuz? Yanılıyor olabilirim (devam eden bir şey olabilir) ama bir soruna neden olabilir gibi görünüyor.


0

Diğer insanların kodlarını okumak zor, ama bu olası (tamamen beyin fırtınası) bir geçici çözüm olduğunu düşünüyorum, ancak tabii ki test edemiyorum:

  1. Çarpışma algılama gerçekleşmeden önce oyuncuların hızını geçici bir değişkene kaydedin.
  2. Çarpışma tepkinizi yaptıktan sonra, X veya Y oyuncularının düzeltilip düzeltilmediğini kontrol edin
  3. X konumu değiştirildiyse, oyuncuların hızını yanıttan önceki hızına manuel olarak sıfırlayın (bir çeşit "güvenlik sıfırlaması" olarak).

Bu arada, oyuncularınız atlama sırasında çatıya çarptığında mevcut kodunuzla ne olur?


Hızın değiştirilmesi hiçbir şeyi çözmez, çünkü hız çarpışma tepkisinden etkilenmez. Yanıt, oyuncunun Konumunu değiştirir ve Hız'ı değiştirmez. Oyuncu çatıya çarptığında, bir süre yüzer, sonra geri gelir. Bu, tavana çarptığında Hızı 0'a ayarlamam nedeniyle amaçlanmıştır.
Vittorio Romeo

GetOverlapVector yönteminde sonuç vektör bileşenlerinden herhangi birini sıfıra ayarlayan kodu kaldırırsanız ne olur?
TravisG

Varlık çapraz olarak dışarı itilir, bazen doğru bile çalışmaz, bazen de bir ızgaradaymış gibi yapışır.
Vittorio Romeo

Şu an hiçbir anlam ifade edemiyorum. Varlığınızın dışarı itilme şekli, çarpıştığı bedenle olan mesafesine bağlı olmalıdır, ancak algoritmanız zaten bunu yapar. Yarın tekrar bakacağım.
TravisG
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.