एक प्लैटफॉर्मर का निर्माण - यह कैसे निर्धारित किया जाए कि किसी खिलाड़ी को कूदने की अनुमति है या नहीं?


16

मैं एक साधारण प्लेटफॉर्मर जंप एन 'रन स्टाइल गेम बना रहा हूं। मैं टाइलों का उपयोग नहीं करता - इसके बजाय मेरे स्तर की संस्थाओं के लिए ज्यामितीय आकार हैं (और खिलाड़ी एक भी है)। मैंने अपनी टक्कर का पता लगाने का कोड पूरा कर लिया है और अब तक सब कुछ ठीक है।

आगे, मैं जंपिंग को लागू करना चाहता था। यदि खिलाड़ी उपयुक्त कुंजी मारता है और कुछ ऊपर की तरफ वेग जोड़ रहा है, तो बस जाँच करना। ठीक काम करता है। लेकिन यह तब भी काम करता है जब खिलाड़ी हवा में हो, जो मैं नहीं चाहता। ;-)

इसलिए, मुझे जांचना होगा कि खिलाड़ी किसी चीज पर खड़ा है या नहीं। मेरा पहला विचार यह था कि अगर अंतिम फ्रेम में टक्कर थी और खिलाड़ी को "कूदने में सक्षम" के रूप में चिह्नित किया गया था, लेकिन यह तब भी ट्रिगर होगा जब खिलाड़ी दीवार में हवा मारता है। जैसा कि मेरा गणित कौशल अच्छा नहीं है, मैं मदद के लिए कहता हूं - यहां तक ​​कि संकेत यह कैसे लागू करेंगे।

धन्यवाद!

जवाबों:


14

दो विकल्प वसंत मन:

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

सामान्य जांच मुझे एक महान विचार की तरह लगती है। पोस्ट करने के लिए धन्यवाद।
क्रिस्टोफर हॉरेंस्टीन

सामान्य जाँच के लिए +1। यह सुनिश्चित करता है कि कोई भी फर्श बिना किसी मुद्दे के बिना दीवार में संक्रमण कर सकता है।
सोवियुत

1
+1 निश्चित रूप से टक्कर-सामान्य की जाँच करें। विभिन्न प्रकार की विश्व-ज्यामिति ठीक है और अधिक लचीले स्तर के डिजाइन के लिए अनुमति देता है, लेकिन यह आपको प्राथमिक मुद्दे को हल नहीं करता है। एक "दीवार" भी "ग्राउंड" प्रकार की हो सकती है, यह निर्भर करता है कि आप उसमें चल रहे हैं या उस पर खड़े हैं। यहीं से टकराव-सामान्य में मदद मिलेगी।
बुम्ज़ैक

मुझे सामान्य समाधान बहुत अच्छा लगता है और इससे मेरी समस्या हल हो जाएगी। यहां तक ​​कि अन्य उच्च श्रेणी का उत्तर अच्छा है और ऐसा है - लेकिन यह मेरे सवाल का बेहतर जवाब देता है। आपका शुक्रिया!
मैलक्स

8

आपको निश्चित रूप से कुछ प्रकार की सतह को लागू करना चाहिए। इसके बारे में सोचें, यदि आप सीढ़ी पर चढ़ सकते हैं तो आप कैसे प्रबंधित करेंगे यदि आप नहीं जान सकते कि क्या आपका चरित्र सिर्फ दीवार या सीढ़ी से टकराया है? आप विरासत का उपयोग करके एक प्रकार की पदानुक्रम का प्रबंधन करने के लिए ओओपी का उपयोग कर सकते हैं, लेकिन मैं आपको एक एनुमरेटेड प्रकार का उपयोग करके कार्यान्वित "श्रेणियों" का उपयोग करने का सुझाव दूंगा:

यह विचार है: एक "Collisions" गणन प्रत्येक श्रेणी के लिए एक झंडा है। उदाहरण के लिए:

namespace Collisions
{
    enum Type
    {
        None   = 0,
        Floor  = 1 << 0,
        Ladder = 1 << 1,
        Enemy  = 1 << 2,
        ... // And whatever else you need.

        // Then, you can construct named groups of flags.
        Player = Floor | Ladder | Enemy
    };
}

इस पद्धति से, आप यह जांचने में सक्षम होंगे कि क्या खिलाड़ी सिर्फ आपके द्वारा प्रबंधित की जाने वाली किसी चीज़ से टकराया है, इसलिए आपका इंजन इकाई के "Collered" तरीके को कॉल कर सकता है:

void Player::Collided( Collisions::Type group )
{
   if ( group & Collisions::Ladder )
   {
      // Manage Ladder Collision
   }
   if ( group & Collisions::Floor )
   {
      // Manage Floor Collision
   }
   if ( group & Collisions::Enemy )
   {
      // Manage Enemy Collision
   }
}

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

void PhysicEngine::OnCollision(...)
{
    mPhysics.AddContact( body1, body1.GetFilter(), body2, body2.GetFilter() );
}

क्या एनम के बजाय कॉन्स्ट इन्ट का उपयोग करने का कोई कारण है? एकल ध्वज या नामित समूह के पतित मामले में प्रगणित प्रकार अधिक पठनीय है, और आपको अधिकांश संकलक में अतिरिक्त प्रकार की जाँच करने की क्षमता मिलती है।

हाँ, एनम नए कस्टम समूह बनाने के लिए बाइनरी ऑपरेटरों का उपयोग नहीं कर सकता (मुझे लगता है)। मैंने थिस कॉन्स्ट क्यों बनाया इसका कारण यह है कि मैं कॉन्फ़िगर पैरामीटर की सुरक्षा को ध्यान में रखते हुए पठनीय कारणों के लिए सार्वजनिक स्थैतिक सदस्यों के साथ एक कॉन्फ़िगर क्लास का उपयोग करता हूं।
Frédérick Imbeault

यह। गणना "रूवल" अन्य निरंतर मूल्यों पर बिटवाइज़ ऑपरेशन हो सकता है (मुझे लगता है कि यह वास्तव में कोई भी स्थिर अभिव्यक्ति हो सकती है, लेकिन मैं मानक की जांच करने के लिए बहुत आलसी हूं)। गैर-स्थिर मूल्य आपके उदाहरण के समान ही प्राप्त किए जाते हैं, लेकिन अधिक सटीक रूप से टाइप किए जाते हैं। मुझे नहीं पता कि आपका "सुरक्षा" से क्या मतलब है, लेकिन एक वर्ग के साथ जुड़े ओवरहेड के बिना एक ही वाक्यविन्यास एक नाम स्थान के साथ प्राप्त किया जा सकता है।

मैंने एन्यूमरेटेड प्रकार का उपयोग करने के लिए आपके कोड उदाहरणों को अपडेट किया।

शायद यह सोचने में आसान बनाता है। मैंने आपके द्वारा किए गए परिवर्तनों की सराहना की, मेरे द्वारा उपयोग की गई विधि सही थी लेकिन मैंने स्पष्टीकरण के लिए कोड को समायोजित नहीं किया था, सुधारों के लिए धन्यवाद। नामस्थान के लिए, आप काफी सही हैं, लेकिन यह सभी भाषाओं के लिए सही नहीं है (उदाहरण के लिए स्क्रिप्टिंग भाषाएँ)। "सुरक्षा" यह है कि मेरे कॉन्फ़िगर विकल्प स्थिर हैं, इसलिए उन्हें संशोधित नहीं किया जा सकता है, लेकिन एक एनम का उपयोग करके इसे भी रोकना है।
मई को Frédérick Imbeault

1

यदि आप एक निश्चित दूरी तक चरित्र के नीचे अपने चरित्र के पैर को समान मानते हैं, और यदि आप सतह से दूर नहीं जा रहे हैं, तो आपका चरित्र जमीन पर है।

मोटे छद्म कोड में:

bool isOnGround(Character& chr)
{
   // down vector is opposite from your characters current up vector.
   // if you want to support wall jumps, animate the vecToFoot as appropriate.
   vec vecToFoot = -chr.up * chr.footDistanceFromCentre;

// if feet are moving away from any surface, can't be on the ground if (dot(chr.velocity, down) < 0.0f) return false;

// generate line from character centre to the foot position vec linePos0 = chr.position; vec linePos1 = chr.position + vecToFoot;

// test line against world. If it returns a hit surface, we're on the ground if (testLineAgainstWorld(line0, line1, &surface) return true;

return false; }


यह काम नहीं करेगा यदि आप डबल जंप, या दीवार कूद जैसे फीचर्स जोड़ना चाहते हैं, तो मुझे लगता है?
Frédérick Imbeault

मुझे विश्वास नहीं है कि ओपी ने डबल जंप या दीवार कूद का उल्लेख किया था, क्या उसने?
जपावर

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

यह मूल रूप से टकराव की सामान्य जांच का एक कम लचीला तरीका है। (कम लचीला है क्योंकि आप सामान्य दिशा की जाँच करके छत की छलांग से दीवार कूद को तुच्छ रूप से अलग कर सकते हैं।)

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