Microsoft XNA प्लेटफ़ॉर्मर उदाहरण, क्या Collsion Detection को सही तरीके से लागू किया गया है?


11

Microsoft द्वारा प्रदान किया गया उदाहरण ऐसा लगता है जैसे टक्कर का पता लगाने (जो मैं देख सकता हूं) में एक छोटी सी त्रुटि होगी। जब उपयोगकर्ता एक Unpassable टाइल से टकराता है, तो चौराहे की गहराई की गणना की जाती है। गहराई मान X और Y का उपयोग उपयोगकर्ता की स्थिति को ठीक करने के लिए किया जाता है ताकि यह टाइल से न टकराए। लेकिन अगर उपयोगकर्ता तिरछे यात्रा कर रहा था, तो यह परिणाम उपयोगकर्ता के लिए ठीक उसी बिंदु पर समाप्त नहीं हो सकता था जहां चरित्र पहले टाइल से टकराएगा?

मैं शायद गलत हूं, लेकिन मैं इसे देख रहा हूं।

   private void HandleCollisions()
        {
            // Get the player's bounding rectangle and find neighboring tiles.
            Rectangle bounds = BoundingRectangle;
            int leftTile = (int)Math.Floor((float)bounds.Left / Tile.Width);
            int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1;
            int topTile = (int)Math.Floor((float)bounds.Top / Tile.Height);
            int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1;

            // Reset flag to search for ground collision.
            isOnGround = false;

            // For each potentially colliding tile,
            for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    // If this tile is collidable,
                    TileCollision collision = Level.GetCollision(x, y);
                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = Level.GetBounds(x, y);
                        Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
                        if (depth != Vector2.Zero)
                        {
                            float absDepthX = Math.Abs(depth.X);
                            float absDepthY = Math.Abs(depth.Y);

                            // Resolve the collision along the shallow axis.
                            if (absDepthY < absDepthX || collision == TileCollision.Platform)
                            {
                                // If we crossed the top of a tile, we are on the ground.
                                if (previousBottom <= tileBounds.Top)
                                    isOnGround = true;

                                // Ignore platforms, unless we are on the ground.
                                if (collision == TileCollision.Impassable || IsOnGround)
                                {
                                    // Resolve the collision along the Y axis.
                                    Position = new Vector2(Position.X, Position.Y + depth.Y);

                                    // Perform further collisions with the new bounds.
                                    bounds = BoundingRectangle;
                                }
                            }
                            else if (collision == TileCollision.Impassable) // Ignore platforms.
                            {
                                // Resolve the collision along the X axis.
                                Position = new Vector2(Position.X + depth.X, Position.Y);

                                // Perform further collisions with the new bounds.
                                bounds = BoundingRectangle;
                            }
                        }
                    }
                }
            }

            // Save the new bounds bottom.
            previousBottom = bounds.Bottom;
        }

3
माइनस 1, पीपीएल क्यों? प्रश्न मेरे लिए मान्य है। लेकिन यहाँ एक छोटा सा जवाब है: प्लेटफ़ॉर्मर डेमो जो कि XNA के साथ आता है, वैसे भी एक उदाहरण है। अपने खेल के लिए एक मॉडल के रूप में कड़ाई से पालन नहीं किया जाना चाहिए। यह आपको दिखाना है कि एक खेल किया जा सकता है। यदि आप इसे लागू नहीं करते हैं तो आपको परेशान नहीं होना चाहिए।
गुस्तावो मैकील

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

जवाबों:


12

आप बिलकुल सही हैं । मेरे पास XNA प्लेटफ़ॉर्मर नमूना पर टक्कर रूटीन के साथ समस्याओं का मेरा हिस्सा है। लेकिन मैं नमूने में दिए गए कोड से शुरू करने में कामयाब रहा, और इसे थोड़ा संशोधित किया जब तक कि मैं हर परीक्षण परिदृश्य में लगातार परिणाम प्राप्त नहीं कर पाया, जो मैं इसे फेंक सकता था।

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

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

और अगर मुझे सही से याद है, तो इसका वास्तविक कारण कुछ इस तरह था:

यहाँ छवि विवरण दर्ज करें


1
डेविड हमेशा XNA पर पिंग करता है!
गुस्तावो मैकील

1
@ गुस्तावो-गुतोकू मैं थोड़े को लगा कि उसे अभी भी समस्या का खाका खींचने की जरूरत है: पी
डेविड गौविया

1
बस यह जवाब आया - महान काम! धन्यवाद डेविड।
ऑस्टिन ब्रुंकहर्स्ट

1

जब आपके पास कई टकराव होते हैं, यदि आप अपने टकरावों को अपने निकटतम आयत के केंद्र से सबसे दूर से दूर करते हैं, तो आपको "फांसी" का मुद्दा नहीं होगा।

1) सभी टकराने वाली आयतों का पता लगाएं

2) यदि एक से अधिक हैं (आपके उपयोग के मामले के आधार पर यह लगातार या असंगत हो सकता है), तो निकटतम खोजें।

3) एक समय में टकरावों को हल करें और जांचें कि क्या अन्य अभी भी वैध टक्कर हैं

स्वीकृत उत्तर में टकराव और इनपुट तर्क मैला है; इसमें हेडिंग आदि को निर्धारित करने के लिए जाँचें हैं। इसे वर्णित तरीके से लागू करने पर टकराव तर्क को आवश्यक होने पर दूरी की गणना की लागत पर इनपुट तर्क से अलग रखा जाता है।

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