AABB टकराव के साथ प्लेटफार्म जम्पिंग की समस्या


9

आरेख पहले देखें:

जब मेरा एएबीबी भौतिकी इंजन एक चौराहे को हल करता है, तो ऐसा उस अक्ष को खोजने से होता है जहां प्रवेश छोटा होता है, फिर उस धुरी पर इकाई को "बाहर" धकेलें।

"जंपिंग मूविंग लेफ्ट" उदाहरण को ध्यान में रखते हुए:

  • यदि वेग x वेग से बड़ा है, तो AABB इकाई को Y अक्ष पर धकेलता है, प्रभावी रूप से कूद को रोकता है (परिणाम: खिलाड़ी मध्य-वायु में रुक जाता है)।
  • यदि वेलोसिटीएक्स वेलोसिटवाई (आरेख में नहीं दिखाया गया है) से छोटा है, तो कार्यक्रम उद्देश्य के अनुसार काम करता है, क्योंकि एएबीबी एक्स अक्ष पर इकाई को बाहर धकेलता है।

इस समस्या का समाधान किस प्रकार से किया जा सकता है?

सोर्स कोड:

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
  • यदि आपने पहले ही ऐसा नहीं किया है तो अपने सभी सहायक कार्यों (दूसरे कोड लिस्टिंग में) का परीक्षण करें।
  • कल्पना करें या मानक आउटपुट पर प्रिंट करें कि ये ऑब्जेक्ट क्या करते हैं। सुनिश्चित करें कि आप जानते हैं कि प्रत्येक कोड क्या करता है और यह पूरी तरह से करता है।
  • टकरावों में बहुत अधिक जानकारी है http://www.flipcode.com/archives/Theory_P Practice- Issue_01_Collision_Detection.shtml

मैंने सिर्फ उस कोड को देखा है जिसे मैंने साबित करने की कोशिश नहीं की है कि यह कहां गलत है।

मैंने कोड को देखा और ये 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 स्थिति को बदल दिया गया है, तो मैन्युअल रूप से रीसेट करें (एक प्रकार के "सुरक्षा रीसेट" के रूप में) खिलाड़ियों को वाई वेग उस प्रतिक्रिया से पहले था।

वैसे, आपके वर्तमान कोड के साथ क्या होता है जब आपके खिलाड़ी कूदते समय छत से टकराते हैं?


वेग बदलने से कुछ हल नहीं होगा, क्योंकि टक्कर की प्रतिक्रिया से वेग अप्रभावित रहता है। प्रतिक्रिया बस खिलाड़ी की स्थिति बदल जाती है, वेग को अपरिवर्तित छोड़ देती है। जब खिलाड़ी छत से टकराता है, तो वह थोड़ी देर के लिए तैरता है और फिर वापस नीचे आता है। यह इरादा है क्योंकि मैं 0 को वेग सेट नहीं कर रहा हूँ जब यह छत से टकराता है।
विटोरियो रोमियो

GetOverlapVector पद्धति में शून्य करने के लिए परिणाम वैक्टर घटकों में से किसी एक को सेट करने वाला कोड निकालने पर क्या होता है?
ट्रैविसग

इकाई तिरछे बाहर धकेल दी जाती है, कभी-कभी यह सही ढंग से काम भी नहीं करती है, दूसरी बार जब यह ग्रिड पर होता है, तो यह इसे ठीक से नहीं खींचता है।
विटोरियो रोमियो

मैं अभी इसका कोई मतलब नहीं निकाल सकता। जिस तरह से आपकी इकाई को बाहर धकेला जाता है, उसे उस शरीर से उसकी दूरी पर निर्भर होना चाहिए, जिससे वह टकरा रहा है, लेकिन आपका एल्गोरिथ्म पहले से ही ऐसा करता है। मैं कल इसे देखूंगा।
ट्रैविसग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.