बॉल टू बॉल कोलिशन - डिटेक्शन एंड हैंडलिंग


266

स्टैक ओवरफ्लो समुदाय की मदद से मैंने एक बहुत ही बुनियादी लेकिन मजेदार भौतिकी सिम्युलेटर लिखा है।

वैकल्पिक शब्द

आप एक गेंद लॉन्च करने के लिए माउस को क्लिक करते हैं और खींचते हैं। यह चारों ओर उछल जाएगा और अंततः "मंजिल" पर रुक जाएगा।

मेरी अगली बड़ी विशेषता जो मैं जोड़ना चाहता हूं वह है बॉल टू बॉल टक्कर। गेंद की गति कुल्हाड़ी और y गति वेक्टर में टूट जाती है। मेरे पास गुरुत्वाकर्षण है (प्रत्येक चरण में y वेक्टर की छोटी कमी), मुझे घर्षण है (दोनों वैक्टर की छोटी कमी प्रत्येक दीवार से टकराती है)। गेंद ईमानदारी से आश्चर्यजनक रूप से चारों ओर घूमती है।

मुझे लगता है कि मेरे प्रश्न के दो भाग हैं:

  1. बॉल टू बॉल टकराव का पता लगाने का सबसे अच्छा तरीका क्या है?
    क्या मेरे पास एक O (n ^ 2) लूप है जो प्रत्येक गेंद पर पुनरावृत्त करता है और यह देखने के लिए हर दूसरी गेंद की जांच करता है कि क्या यह त्रिज्या ओवरलैप है?
  2. गेंद को गेंद से टकराने के लिए मैं किन समीकरणों का उपयोग करता हूं? भौतिकी 101
    यह दो गेंदों की गति x / y वैक्टर को कैसे प्रभावित करता है? परिणामी दिशा दो गेंदों को किस दिशा में ले जाती है? मैं इसे प्रत्येक गेंद पर कैसे लागू करूं?

वैकल्पिक शब्द

"दीवारों" की टक्कर का पता लगाने से निपटने और परिणामस्वरूप वेक्टर परिवर्तन आसान थे लेकिन मुझे गेंद-गेंद टकराव के साथ अधिक जटिलताएं दिखाई देती हैं। दीवारों के साथ मुझे बस उपयुक्त एक्स या वाई वेक्टर का नकारात्मक लेना था और इसे सही दिशा में जाना होगा। गेंदों के साथ मुझे नहीं लगता कि यह इस तरह है।

कुछ त्वरित स्पष्टीकरण: सादगी के लिए मैं अब के लिए एक पूरी तरह से लोचदार टकराव के साथ ठीक हूं, मेरी सभी गेंदों में अभी एक ही द्रव्यमान है, लेकिन मैं भविष्य में इसे बदल सकता हूं।


संपादित करें: संसाधन जिन्हें मैंने उपयोगी पाया है

वैक्टर के साथ 2d बॉल फिजिक्स: ट्रिगोनोमेट्री के बिना 2-डायमेंशनल कॉल्स। पीपीडी
2 डी बॉल टकराव का पता लगाने का उदाहरण: कोलिशन डिटेक्शन जोड़ना


सफलता!

मैं गेंद टकराव का पता लगाने और प्रतिक्रिया महान काम कर रहा है!

प्रासंगिक कोड:

टक्कर की पहचान हुई है:

for (int i = 0; i < ballCount; i++)  
{  
    for (int j = i + 1; j < ballCount; j++)  
    {  
        if (balls[i].colliding(balls[j]))  
        {
            balls[i].resolveCollision(balls[j]);
        }
    }
}

यह हर गेंद के बीच टकराव की जाँच करेगा, लेकिन निरर्थक जाँच छोड़ें (यदि आपको जाँचना है कि क्या गेंद 1 गेंद 2 से टकराती है तो आपको यह जाँचने की ज़रूरत नहीं है कि क्या गेंद 2 गेंद से टकराती है। साथ ही, यह अपने आप टकराव की जाँच कर लेती है )।

फिर, मेरी बॉल क्लास में मेरे टकराने () और सॉलोकेशन () तरीके हैं:

public boolean colliding(Ball ball)
{
    float xd = position.getX() - ball.position.getX();
    float yd = position.getY() - ball.position.getY();

    float sumRadius = getRadius() + ball.getRadius();
    float sqrRadius = sumRadius * sumRadius;

    float distSqr = (xd * xd) + (yd * yd);

    if (distSqr <= sqrRadius)
    {
        return true;
    }

    return false;
}

public void resolveCollision(Ball ball)
{
    // get the mtd
    Vector2d delta = (position.subtract(ball.position));
    float d = delta.getLength();
    // minimum translation distance to push balls apart after intersecting
    Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / getMass(); 
    float im2 = 1 / ball.getMass();

    // push-pull them apart based off their mass
    position = position.add(mtd.multiply(im1 / (im1 + im2)));
    ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));

    // impact speed
    Vector2d v = (this.velocity.subtract(ball.velocity));
    float vn = v.dot(mtd.normalize());

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
    Vector2d impulse = mtd.normalize().multiply(i);

    // change in momentum
    this.velocity = this.velocity.add(impulse.multiply(im1));
    ball.velocity = ball.velocity.subtract(impulse.multiply(im2));

}

स्रोत कोड: बॉल को बॉल कोलाइडर के लिए पूर्ण स्रोत।

अगर किसी के पास इस बुनियादी भौतिकी सिम्युलेटर को बेहतर बनाने के लिए कुछ सुझाव हैं तो मुझे बताएं! एक चीज़ जो मुझे अभी तक मिलनी है वह है कोणीय गति इसलिए गेंदें अधिक वास्तविक रूप से चलेंगी। कोई अन्य सुझाव? एक टिप्पणी छोड़ें!


16
मुझे नहीं लगता कि यह एल्गोरिथ्म काफी अच्छा है क्योंकि अगर आपकी गेंदें बहुत तेजी से आगे बढ़ रही हैं (पूर्व: तेजी से तो 2 * त्रिज्या प्रति फ्रेम, एक गेंद बिना किसी टक्कर के दूसरी गेंद से गुजर सकती है।
बेन्जी मिजराही

@Simulcal क्या आप अपना सोर्स कोड फिर से अपलोड कर सकते हैं (सभी lodropper.com लिंक टूटे हुए दिखाई देते हैं)। इसके अलावा, आप जिस पीडीएफ फाइल को प्राप्त कर सकते हैं, उसे [geocities.com/vobarian/2dcollisions/2dcollisions.pdf] से हटा दें, क्योंकि
जियोकॉटी

1
: यहाँ BallBounce मैं के पिछले संस्करण के लिए एक लिंक पर काम किया है dl.dropbox.com/u/638285/ballbounce.rar
mmcdole

@ सभी ने योगदान दिया: क्या आप इस इंजन को 3D में बदलने के लिए कुछ प्रकाश डाल सकते हैं? यह बेहतरीन इंजन Java3D में भी कैसे काम कर सकता है।
स्थैतिक शून्य मुख्य

2
लाइन Vector2d impulse = mtd.multiply(i);मैं * सामान्यीकृत mtd वेक्टर होना चाहिए। कुछ इस तरह:Vector2d impulse = mtd.normalize().multiply(i);
20

जवाबों:


117

यह पता लगाने के लिए कि क्या दो गेंदें टकराती हैं, बस यह जांचें कि उनके केंद्रों के बीच की दूरी त्रिज्या से दो गुना से कम है या नहीं। गेंदों के बीच पूरी तरह से लोचदार टकराव करने के लिए, आपको केवल उस वेग के घटक के बारे में चिंता करने की ज़रूरत है जो टकराव की दिशा में है। अन्य घटक (टकराव के लिए स्पर्शरेखा) दोनों गेंदों के लिए समान रहेंगे। आप एक गेंद से दूसरी दिशा में एक यूनिट वेक्टर पॉइंट बनाकर टक्कर के घटक प्राप्त कर सकते हैं, फिर गेंदों के वेग वैक्टर के साथ डॉट उत्पाद ले सकते हैं। फिर आप इन घटकों को 1 डी पूरी तरह से लोचदार टकराव समीकरण में प्लग कर सकते हैं।

विकिपीडिया में पूरी प्रक्रिया का बहुत अच्छा सारांश है । किसी भी द्रव्यमान की गेंदों के लिए, समीकरणों का उपयोग करके नए वेगों की गणना की जा सकती है (जहां v1 और v2 टक्कर के बाद के वेग हैं, और u1, u2 पहले से हैं):

v_ {1} = \ frac {u_ {1} (m_ {1} -m_ {2}) + 2m_ {2} u_ {2}} {m_ {1} + m_ {2}}

v_ {2} = \ frac {u_ {2} (m_ {2} -m_ {1}) + 2m_ {1} u_ {1}} {m_ {1} + m_ {2}}

यदि गेंदों में समान द्रव्यमान है तो वेगों को बस स्विच किया जाता है। यहाँ कुछ कोड मैंने लिखा है जो कुछ इसी तरह का है:

void Simulation::collide(Storage::Iterator a, Storage::Iterator b)
{
    // Check whether there actually was a collision
    if (a == b)
        return;

    Vector collision = a.position() - b.position();
    double distance = collision.length();
    if (distance == 0.0) {              // hack to avoid div by zero
        collision = Vector(1.0, 0.0);
        distance = 1.0;
    }
    if (distance > 1.0)
        return;

    // Get the components of the velocity vectors which are parallel to the collision.
    // The perpendicular component remains the same for both fish
    collision = collision / distance;
    double aci = a.velocity().dot(collision);
    double bci = b.velocity().dot(collision);

    // Solve for the new velocities using the 1-dimensional elastic collision equations.
    // Turns out it's really simple when the masses are the same.
    double acf = bci;
    double bcf = aci;

    // Replace the collision velocity components with the new ones
    a.velocity() += (acf - aci) * collision;
    b.velocity() += (bcf - bci) * collision;
}

जैसा कि दक्षता के लिए, रयान फॉक्स सही है, आपको इस क्षेत्र को खंडों में विभाजित करने पर विचार करना चाहिए, फिर प्रत्येक अनुभाग के भीतर टकराव का पता लगाना चाहिए। ध्यान रखें कि गेंदें एक खंड की सीमाओं पर अन्य गेंदों के साथ टकरा सकती हैं, इसलिए यह आपके कोड को और अधिक जटिल बना सकता है। दक्षता शायद तब तक मायने नहीं रखती जब तक आपके पास कई सौ गेंदें न हों। बोनस अंक के लिए, आप प्रत्येक अनुभाग को एक अलग कोर पर चला सकते हैं, या प्रत्येक अनुभाग के भीतर टकराव के प्रसंस्करण को विभाजित कर सकते हैं।


2
दो गेंदों का द्रव्यमान समान नहीं है। गेंदों के बीच वेक्टर परिवर्तन को कैसे प्रभावित करता है?
mmcdole

3
12 वीं कक्षा के बाद से कुछ समय हो गया है, लेकिन मुझे लगता है कि उन्हें द्रव्यमान के अनुपात के अनुरूप गति मिलती है।
रयान फॉक्स

6
@ जय, केवल इंगित करने के लिए .. कि आपके द्वारा जोड़े गए एक समीकरण छवि 1 आयामी टकराव के लिए है, 2 आयामी नहीं।
mmcdole

@simucal। सच नहीं है ... यू और वी उस समीकरण में वैक्टर हैं। यही है, उनके पास x, y (और z) घटक हैं।
एंड्रयू रोलिंग

2
@Simucal, आप सही हैं, वे एक आयामी मामले के लिए हैं। अधिक आयामों के लिए, बस उस वेग के घटकों का उपयोग करें जो टक्कर के अनुरूप हैं (aci, bci in code)। अन्य घटक टकराव के लिए रूढ़िवादी हैं और बदल नहीं जाएंगे, इसलिए आपको उनके बारे में चिंता करने की आवश्यकता नहीं है।
बजे जे कॉनरोड

48

खैर, सालों पहले जैसा कार्यक्रम आपने यहां प्रस्तुत किया था।
एक छिपी हुई समस्या है (या कई, बिंदु पर निर्भर करता है):

  • यदि गेंद की गति बहुत अधिक है, तो आप टकराव को याद कर सकते हैं।

और यह भी, लगभग 100% मामलों में आपकी नई गति गलत होगी। खैर, गति नहीं है , लेकिन पदों । आप नए गति की गणना करने के लिए है ठीक सही जगह में। अन्यथा आप बस कुछ छोटी "त्रुटि" राशि पर गेंदों को स्थानांतरित करते हैं, जो पिछले असतत कदम से उपलब्ध है।

समाधान स्पष्ट है: आपको टाइमस्टेप को विभाजित करना होगा, ताकि पहले आप सही जगह पर शिफ्ट हो जाएं, फिर टकराएं, फिर आपके पास शेष समय के लिए शिफ्ट हो जाएं।


यदि पदों को स्थानांतरित किया जाता है timeframelength*speed/2, तो पदों को सांख्यिकीय रूप से तय किया जाएगा।
नैकिलोन

@ नाकिलोन: नहीं, यह केवल कुछ मामलों में मदद करता है, लेकिन आम तौर पर टकराव को याद करना संभव है। और टकराव को याद करने की संभावना टाइमफ्रेमेलम के आकार के साथ बढ़ जाती है। वैसे, ऐसा लगता है कि अलेफ ने सही समाधान का प्रदर्शन किया (मैंने हालांकि इसे स्किम्ड किया)।
avp

1
@avp, मैं इस बारे में नहीं था कि अगर गेंद की गति बहुत अधिक है, तो आप टकराव को याद कर सकते हैं। , लेकिन आपके नए पदों के बारे में गलत होगा । टक्कर के कारण थोड़ा बाद में पता लगाया जा रहा है, क्योंकि वे वास्तव में टकरा गए थे, अगर timeframelength*speed/2उस स्थिति से अलग हो जाते हैं, तो सटीकता दो बार बढ़ जाएगी।
नैकिलोन

20

इस समस्या को हल करने के लिए आपको अंतरिक्ष विभाजन का उपयोग करना चाहिए।

बाइनरी स्पेस पार्टिशनिंग और क्वाडट्रैस पर पढ़ें


4
अंतरिक्ष विभाजन के बजाय, एक स्वीप और प्रुन एल्गोरिथ्म बेहतर काम नहीं करेगा? गेंदें तेजी से आगे बढ़ रही हैं, इसलिए किसी भी विभाजन को बार-बार अपडेट करना होगा, ओवरहेडिंग करना। एक स्वीप और प्रून किसी भी क्षणिक डेटा संरचनाओं के बिना, ओ (एन लॉग एन) में सभी टकराते जोड़े को पा सकते थे। यहाँ मूल बातें के लिए एक अच्छा ट्यूटोरियल है
ह्यूगो

13

रयान फॉक्स द्वारा सुझाव को स्पष्टीकरण के रूप में क्षेत्रों में स्क्रीन को विभाजित करने के लिए, और केवल क्षेत्रों के भीतर टकराव के लिए जाँच ...

उदाहरण के लिए प्ले एरिया को चौकों के ग्रिड में विभाजित करें (जो मनमाने ढंग से कहेंगे 1 यूनिट लंबाई प्रति पक्ष), और प्रत्येक ग्रिड वर्ग के भीतर टकराव की जाँच करें।

यह बिल्कुल सही समाधान है। इसके साथ एकमात्र समस्या (जैसा कि एक अन्य पोस्टर ने बताया है) यह है कि सीमाओं के पार टकराव एक समस्या है।

इसका समाधान 0.5 यूनिट के एक दूसरे ग्रिड को पहले एक को ऊर्ध्वाधर और क्षैतिज ऑफसेट से ओवरले करना है।

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


+1 अधिक सटीक समाधान के लिए, और कायर-ड्राइव डाउनवॉटर से मुकाबला करने के लिए
स्टीवन ए। लोव

1
वह एक अच्छा विचार है। मैंने एक बार ऐसा किया था और मैंने वर्तमान सेल और सभी पड़ोसी कोशिकाओं की जांच की, लेकिन आपका तरीका अधिक कुशल है। दूसरा तरीका जो मैंने अभी सोचा था कि वर्तमान सेल की जांच करना है, और फिर यह देखने के लिए जांचें कि क्या यह वर्तमान कोशिकाओं की सीमाओं के साथ प्रतिच्छेद करता है, और यदि ऐसा है, तो उन चीजों को पड़ोसी सेल में जांचें।
LoveMeSomeCode

10

टकराव की संख्या को कम करने का एक अच्छा तरीका स्क्रीन को विभिन्न वर्गों में विभाजित करना है। आप तब प्रत्येक गेंद की गेंदों की उसी खंड में तुलना करते हैं।


5
सुधार: आप एक ही और आसन्न वर्गों के साथ टकराव के लिए जांच करने की आवश्यकता
प्रिंट करें

7

एक बात मैं यहाँ अनुकूलन करने के लिए देखते हैं।

हालांकि मैं इस बात से सहमत हूं कि जब गेंद उनके रेडी का योग हो तो किसी को भी इस दूरी की गणना नहीं करनी चाहिए! इसके बजाय, इसकी गणना करें कि यह चौकोर है और इस तरह से काम करता है। उस महंगे वर्गमूल संचालन का कोई कारण नहीं है।

इसके अलावा, एक बार जब आपको कोई टक्कर मिल जाती है तो आपको टक्करों का मूल्यांकन करना जारी रखना होगा जब तक कि कोई और अधिक नहीं रहता। समस्या यह है कि पहले एक दूसरों को कारण हो सकता है जिसे आपको सटीक चित्र प्राप्त करने से पहले हल करना होगा। गौर कीजिए कि अगर गेंद किनारे पर गेंद मारती है तो क्या होता है? दूसरी गेंद किनारे से टकराती है और तुरंत पहली गेंद में रिबाउंड हो जाती है। यदि आप कोने में गेंदों के ढेर में धमाका करते हैं तो आपके पास अगले चक्र को पुनरावृत्त करने से पहले काफी कुछ टकराव हो सकते हैं जिन्हें हल करना होगा।

O (n ^ 2) के लिए, आप जो भी कर सकते हैं, उसे अस्वीकार करने की लागत को कम से कम करें:

1) एक गेंद जो हिल नहीं रही है वह कुछ भी नहीं मार सकती है। अगर वहाँ उचित संख्या में गेंदें फर्श पर पड़ी हैं तो इससे बहुत सारे परीक्षण बच सकते हैं। (ध्यान दें कि आपको अभी भी जांचना होगा कि क्या कुछ स्थिर गेंद है।)

2) कुछ ऐसा करने लायक हो सकता है: स्क्रीन को कई क्षेत्रों में विभाजित करें, लेकिन लाइनों को फजी होना चाहिए - एक क्षेत्र के किनारे पर गेंदों को सभी प्रासंगिक (4) हो सकते हैं। मैं एक 4x4 ग्रिड का उपयोग करूंगा, जोनों को बिट्स के रूप में स्टोर करूंगा। यदि दो गेंदों के क्षेत्रों का एक AND परीक्षण के अंत में शून्य देता है।

3) जैसा कि मैंने उल्लेख किया है, वर्गमूल मत करो।


वर्गमूल टिप पर जानकारी के लिए धन्यवाद। वर्ग की तुलना में इसकी महंगी प्रकृति के बारे में पता नहीं था।
mmcdole

एक और अनुकूलन गेंदों को खोजने के लिए होगा जो किसी भी अन्य गेंदों के पास नहीं हैं। यह तभी मज़बूती से काम करेगा जब गेंदों का वेग बाधित होगा।
ब्रैड गिल्बर्ट

1
मैं अलग-थलग गेंदों की तलाश में असहमत हूं। यह टकराव का पता लगाने जितना ही महंगा है। चीजों को बेहतर बनाने के लिए आपको कुछ ऐसा चाहिए जो प्रश्न में गेंद के लिए O (n) से कम हो।
लोरेन Pechtel

7

मुझे 2 डी में टक्कर का पता लगाने और प्रतिक्रिया के बारे में जानकारी के साथ एक उत्कृष्ट पृष्ठ मिला।

http://www.metanetsoftware.com/technique.html

वे यह समझाने की कोशिश करते हैं कि यह अकादमिक दृष्टिकोण से कैसे किया जाता है। वे साधारण ऑब्जेक्ट-टू-ऑब्जेक्ट टकराव का पता लगाने के साथ शुरू करते हैं, और टक्कर की प्रतिक्रिया पर आगे बढ़ते हैं और इसे कैसे स्केल करते हैं।

संपादित करें: अद्यतन लिंक


3

ऐसा करने के लिए आपके पास दो आसान तरीके हैं। जे ने गेंद के केंद्र से जाँच का सही तरीका कवर किया है।

एक आसान तरीका यह है कि एक आयत बाउंडिंग बॉक्स का उपयोग करें, अपने बॉक्स का आकार गेंद के आकार का 80% होना चाहिए, और आप टक्कर को बहुत अच्छी तरह से अनुकरण करेंगे।

अपनी बॉल क्लास में एक विधि जोड़ें:

public Rectangle getBoundingRect()
{
   int ballHeight = (int)Ball.Height * 0.80f;
   int ballWidth = (int)Ball.Width * 0.80f;
   int x = Ball.X - ballWidth / 2;
   int y = Ball.Y - ballHeight / 2;

   return new Rectangle(x,y,ballHeight,ballWidth);
}

फिर, अपने पाश में:

// Checks every ball against every other ball. 
// For best results, split it into quadrants like Ryan suggested. 
// I didn't do that for simplicity here.
for (int i = 0; i < balls.count; i++)
{
    Rectangle r1 = balls[i].getBoundingRect();

    for (int k = 0; k < balls.count; k++)
    {

        if (balls[i] != balls[k])
        {
            Rectangle r2 = balls[k].getBoundingRect();

            if (r1.Intersects(r2))
            {
                 // balls[i] collided with balls[k]
            }
        }
    }
}

1
यह क्षैतिज और ऊर्ध्वाधर टकरावों पर गेंदों को एक दूसरे में 20% तक जाने देगा। दक्षता अंतर नगण्य के रूप में अच्छी तरह से परिपत्र बाउंडिंग बॉक्स का उपयोग कर सकते हैं। भी, (x-width)/2होना चाहिए x-width/2
मार्कस जार्डेरोट

पूर्ववर्ती टाइपो पर अच्छा कॉल। आप पाएंगे कि अधिकांश 2 डी गेम गैर-आयताकार आकृतियों पर आयताकार बाउंडिंग बॉक्स का उपयोग करते हैं क्योंकि यह तेज है, और उपयोगकर्ता लगभग वैसे भी कभी भी नोटिस नहीं करता है।
FlySwat

आप आयताकार बाउंडिंग बॉक्स कर सकते हैं, तो अगर यह एक हिट की जाँच परिपत्र बाउंडिंग बॉक्स है।
ब्रैड गिल्बर्ट

1
@ जोनाथन हॉलैंड, आपका आंतरिक लूप होना चाहिए (int k = i + 1; ...) इससे सभी निरर्थक जांचों से छुटकारा मिल जाएगा। (यानी स्वयं की टक्कर के साथ जाँच करना और बॉल 2 के साथ टकराव बॉल 1 की जाँच करना, फिर बॉल 2 के साथ बॉल 2)।
mmcdole

4
वास्तव में, एक वर्ग सीमांकन बॉक्स होने की संभावना है और भी खराब प्रदर्शन के लिहाज से एक परिपत्र बाउंडिंग बॉक्स से (यह मानते हुए आप वर्गमूल दूर अनुकूलन किया है)
Ponkadoodle

3

मैं देख रहा हूँ कि यह यहाँ और वहाँ संकेत दिया गया है, लेकिन आप पहले एक तेज़ गणना भी कर सकते हैं, जैसे, ओवरलैप के लिए बाउंडिंग बॉक्स की तुलना करें, और जब वह पहला टेस्ट पास करे तो एक त्रिज्या आधारित ओवरलैप करें।

जोड़ / अंतर गणित त्रिज्या के लिए सभी ट्रिगर की तुलना में एक बाउंडिंग बॉक्स के लिए बहुत तेज है, और ज्यादातर बार, बाउंडिंग बॉक्स परीक्षण टकराव की संभावना को खारिज कर देगा। लेकिन यदि आप ट्रिगर के साथ फिर से परीक्षण करते हैं, तो आपको सटीक परिणाम मिल रहे हैं जो आप चाहते हैं।

हाँ, यह दो परीक्षण हैं, लेकिन यह समग्र रूप से तेज़ होगा।


6
आपको ट्रिगर की आवश्यकता नहीं है। bool is_overlapping(int x1, int y1, int r1, int x2, int y2, int r2) { return (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)<(r1+r2)*(r1+r2); }
पोंकडूडल


2

मैंने HTML कैनवस तत्व का उपयोग करके जावास्क्रिप्ट में इस कोड को लागू किया, और इसने 60 फ्रेम प्रति सेकंड पर अद्भुत सिमुलेशन का उत्पादन किया। मैंने यादृच्छिक स्थितियों और वेगों पर एक दर्जन गेंदों के संग्रह के साथ सिमुलेशन शुरू किया। मैंने पाया कि उच्च वेगों में, एक छोटी गेंद और एक बहुत बड़ी गेंद के बीच की एक टक्कर टकराती है, जिससे छोटी गेंद बड़ी गेंद के किनारे पर STICK दिखाई देती है , और अलग होने से पहले बड़ी गेंद के लगभग 90 डिग्री तक ऊपर चली जाती है। (मुझे आश्चर्य है कि अगर किसी और ने इस व्यवहार को देखा।)

गणना के कुछ लॉगिंग से पता चला कि इन मामलों में न्यूनतम अनुवाद दूरी एक ही गेंदों को अगले समय के कदम में टकराने से रोकने के लिए पर्याप्त बड़ी नहीं थी। मैंने कुछ प्रयोग किए और पाया कि मैं सापेक्ष वेग के आधार पर MTD को बढ़ाकर इस समस्या को हल कर सकता हूं:

dot_velocity = ball_1.velocity.dot(ball_2.velocity);
mtd_factor = 1. + 0.5 * Math.abs(dot_velocity * Math.sin(collision_angle));
mtd.multplyScalar(mtd_factor);

मैंने सत्यापित किया कि इस फिक्स से पहले और बाद में, हर टकराव के लिए कुल गतिज ऊर्जा को संरक्षित किया गया था। Mtd_factor में 0.5 मान लगभग एक टकराव के बाद गेंदों को अलग करने के लिए हमेशा पाए जाने वाले मिनीमम मूल्य था।

हालांकि यह फिक्स सिस्टम की सटीक भौतिकी में थोड़ी सी भी त्रुटि का परिचय देता है, लेकिन ट्रेडऑफ यह है कि अब ब्राउज़र में बहुत तेज गेंदों को समय कदम के आकार को कम किए बिना सिम्युलेटेड किया जा सकता है।


1
पाप (..) एक सस्ता कार्य नहीं है
पॉल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.