2012-10-03 50 views
5

मैं पहली बार बॉक्स 2 डी का उपयोग मध्यम आकार के फ़्लैश गेम में गंभीरता से कर रहा हूं जिस पर मैं काम कर रहा हूं। Box2D के साथ मेरा वर्तमान अनुभव दुनिया, निकायों को बनाने और उन निकायों को एक कार्यात्मक तरीके से दुनिया में जोड़ने के लिए सीमित है।मैं अपने सभी बॉक्स 2 डी टकरावों को एक स्वच्छ, प्रबंधनीय ढंग से कैसे ट्रैक कर सकता हूं?

मुझे अपने गेम पर्यावरण में Box2D को एकीकृत करने के लिए काफी आसान लग रहा है, अच्छी तरह से लिखित कोड बनाए रखा है और ट्यूटोरियल से निपटने के माध्यम से चलने वाले कुछ ट्यूटोरियल पूरे किए हैं। अब जिस मुद्दे का सामना कर रहा हूं वह यह है कि मेरे खेल में कई निकायों होंगे, प्रत्येक अलग-अलग तरीकों से अन्य निकायों के साथ बातचीत कर रहा है, और मुझे अपने b2ContactListener सबक्लास को बेहद गन्दा होने के बिना लिखना मुश्किल लगता है।

मैंने उपयोग किए गए एक ट्यूटोरियल के आधार पर, मैंने b2ContactListener का अपना उप-वर्ग बनाया है और BeginContact() विधि का ओवरराइड जोड़ा है। तर्क यह है कि BeginContact() प्राप्त होने पर प्राप्त होता है b2Contact का एक उदाहरण संदर्भित करेगा, जिसके माध्यम से मैं दो b2Fixture उदाहरणों (दो उदाहरणों को टकराया गया) तक पहुंच सकता हूं। मैं फिर उन b2Fixture एस के साथ जुड़े b2Body उदाहरण तक पहुंचने में सक्षम हूं।

  • समस्या: वर्तमान में मैं (यानी कि क्या वे एक दीवार और एक मिसाइल, या खिलाड़ी और एक पेड़, आदि कर रहे हैं) क्या दो बातें टकरा जानने जो GetUserData() और दिखता है का उपयोग करता है की एक राउंडअबाउट रास्ता है एक उदाहरण के रूप में इस तरह:

    var f1Player:Boolean = contact.GetFixtureA().GetBody().GetUserData() is Player 
    var f2Player:Boolean = contact.GetFixtureB().GetBody().GetUserData() is Player 
    var f1Tree:Boolean = contact.GetFixtureA().GetBody().GetUserData() is Tree 
    var f2Tree:Boolean = contact.GetFixtureB().GetBody().GetUserData() is Tree 
    // ... continutes with all possible combinations. 
    
    
    // Example of managing a collision: 
    if(f1Player && f2Tree) 
    { 
        // Player (FixtureA) and Tree (FixtureB) 
    } 
    
    if(f2Player && f1Tree) 
    { 
        // Player (FixtureB) and Tree (FixtureA) 
    } 
    

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

यह स्पष्ट रूप से सही दृष्टिकोण नहीं है, लेकिन मैं संसाधनों का पता लगाने में सक्षम नहीं हूं जो टक्कर पहचान प्रबंधन को और अधिक अच्छी तरह से समझाते हैं।

क्या किसी को भी Box2D का उपयोग करके टक्कर पहचान प्रबंधन के साथ अनुभव है कि वे साझा कर सकते हैं? साथ ही, SetUserData(entityThatOwnsTheBody); का उपयोग उस विधि का उपयोग करने का सही तरीका है?

उत्तर

1

मैं मूल से कुछ ज्यादा अच्छा आया हूं।

सबसे पहले, मेरे पास सिर्फ Being वर्ग है (जो b2Body का मालिक है) अपने शरीर को UserData के रूप में सेट करें। यह वर्ग भी एक onContact() विधि होते हैं और नीचे के समान दिखाई देगें:

public class Being 
{ 

    private var _body:b2Body; 


    public function Being() 
    { 
     // Define the body here. 
     // ... 

     _body.SetUserData(this); 
    } 


    public function onCollision(being:Being = null):void 
    { 
     // 
    } 

} 

फिर अपने ही b2ContactListener कार्यान्वयन में, मैं बस पारित टकराने Being (या अशक्त, अगर है कि वहाँ कोई Being टकराने b2Body करने के लिए आवंटित ' रों UserData) का विरोध Being के onCollision() रहे हैं:

override public function BeginContact(contact:b2Contact):void 
{ 
    var bodyA:b2Body = contact.GetFixtureA().GetBody(); 
    var bodyB:b2Body = contact.GetFixtureB().GetBody(); 

    var beingA:Being = bodyA.GetUserData() as Being || null; 
    var beingB:Being = bodyB.GetUserData() as Being || null; 

    beingA && beingA.onCollision(beingB); 
    beingB && beingB.onCollision(beingA); 
} 

और अंत में Being की मेरी उपवर्गों में से प्रत्येक में, मैं आसानी से एक collisi के लिए तर्क उचित तैयार कर सकते हैं किसी अन्य प्रकार के Being एस के बीच:

class Zombie extends Being 
{ 
    override public function onCollision(being:Being = null):void 
    { 
     if(being && being is Bullet) 
     { 
      // Damage this Zombie and remove the bullet. 
      // ... 
     } 
    } 
} 
+1

लगता है कि लंबे 'अगर' कथन की तरह ही बीइंग क्लास में स्थानांतरित हो जाता है। प्रसंस्करण के लिए कैसे केवल टकराव के लिए एक बार किया जाना चाहिए, उदाहरण के लिए। एक आवाज बजाना या स्कोर में वृद्धि करना। – iforce2d

+0

@ iforce2d यही सच है, मेरा मतलब है वहाँ होना करने के लिए जा रहा है '()' बयान किसी भी तरह से प्रत्येक टक्कर संयोजन के लिए मानदंड जोड़ने के लिए है, लेकिन यह एक फ़ाइल में सब कुछ होने की तुलना में अधिक संगठित लगता है। यह मुझे प्रासंगिक वर्गों के माध्यम से दो चीजों के बीच टकराव आसानी से ढूंढने की क्षमता प्रदान करता है और मुझे यह जांचना नहीं है कि प्रत्येक टक्कर के लिए कौन सा होना है। – Marty

+0

एकल अवसरों के लिए, जिसे व्यक्ति द्वारा प्रबंधित किया जा सकता है, साथ ही सरल 'हैबिन टच किए गए' बूलियन या इसी तरह के द्वारा। – Marty

1

मैं Box2d की c++ संस्करण का उपयोग किया है, लेकिन मुझे लगता है कि एक ही दृष्टिकोण actionscript में काम करेंगे। मैं एक वर्ग Object बनाता हूं, जिसमें b2Body *_body पॉइंटर और ग्राफिकल प्रतिनिधित्व के लिए एक सूचक शामिल है। _body का UserDataObject * पर इंगित करने के लिए सेट किया गया था।

virtual bool acceptsContacts (); 
virtual void onContactBegin  (const ContactData &data); 
virtual void onContactEnded  (const ContactData &data); 
virtual void onContactPreSolve (const ContactData &data); 
virtual void onContactPostSolve (const ContactData &data); 

जब टक्कर b2ContactListener उपवर्ग में पता चला था, यह जाँच टकरा निकायों उपयोगकर्ता डेटा है तो: वर्ग Object निम्न विधियों में था। यदि ऐसा है, तो उसने अपने उपयोगकर्ता डेटा को Object* पर डाला और यदि किसी भी टक्कर वाली वस्तुओं ने संपर्क स्वीकार किए - तो ContactData (टकराव के बारे में सभी आवश्यक जानकारी वाले एक वर्ग) को बनाया और बाद में वितरित करने के लिए इसे आंतरिक list में रखा।

जब b2World::update विधि लौटा दी गई, ContactListener प्रक्रियाओं के लिए ऑब्जेक्ट्स पर सभी संपर्क जानकारी प्रदान करता है।प्रसव में देरी हुई क्रम में आप नए निकायों, जोड़ों बना सकते हैं और इतने पर, सही जब टकराव (जो है, जबकि अद्यतन निष्पादित हो रहा है अनुमति नहीं है)

इसके अलावा प्रसंस्करण आप ContactListener को सूचित करना चाहिए (बस ContactData अंदर यह करने के लिए एक सूचक डाल) अगर टक्कर प्रसंस्करण के दौरान टक्कर वाले शरीर में से एक हटा दिया गया था, इसलिए यह उचित संपर्कों को अमान्य कर सकता है और उन्हें

2

हाँ, यह वास्तव में एक परेशानी का थोड़ा सा है। असल में मुझे लगता है कि आपके पास जिस तरह से है वह काफी विशिष्ट है।

fwiw Box2D को फ़िक्स्चर ओवरलैप करने का परीक्षण करते समय भी इसी तरह की समस्या से निपटना होगा। B2CollideCircles, b2CollidePolygonAndCircle, b2CollidePolygons इत्यादि जैसे कार्यों का एक गुच्छा है, और जब दो जुड़नार एक दूसरे के पास आते हैं तो इंजन चुनता है कि इनमें से किन कार्यों का उपयोग किया जाना चाहिए।

यह एक 2-आयामी सरणी में समारोह संकेत डाल करके करता है, तो सूचकांक के रूप में दो आकार प्रकार का उपयोग करके इस सरणी में उचित समारोह ऊपर लग रहा है। विवरण के लिए b2Contact.cpp में पहले तीन कार्यों को देखें।

बेशक, यदि आप एएस 3 में इस तरह के फ़ंक्शन संदर्भों को पारित नहीं कर सकते हैं तो मुझे लगता है कि यह उत्तर बहुत मदद नहीं करता है, लेकिन मैंने सोचा कि मैं वैसे भी पोस्ट करूंगा क्योंकि सी/सी ++/जेएस उपयोगकर्ता आ सकते हैं।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^