बहुत सारे वर्गों के लिए कुशल टाइल-आधारित टक्कर का पता लगाना?


9

वर्तमान में मैं एक टाइल-आधारित गेम के अपने टेक पर काम कर रहा हूं (टेरारिया के बारे में सोचें, लेकिन कम कल्पनात्मक (मुझे लगता है कि यह एक शब्द है; क्षमा करें यदि यह नहीं है))।

वैसे भी, मेरे पास वर्तमान में टकराव का पता लगाने वाला काम है (कोने के मामलों के लिए भी!) जो मेरे लिए एक बड़ा कदम था। एक ब्लॉक के माध्यम से स्प्राइट नहीं चलाने को देखने के बारे में कुछ बहुत संतुष्टिदायक है। लेकिन तब मुझे बेंचमार्क करने का विचार था। बुरा विचार।

1,000 वर्ग, कोई समस्या नहीं। 10,000 वर्ग, 3 वर्णों के लिए एक प्रकार से पिछड़ गया था। 100,000 वर्ण (वास्तव में बहुत बड़ा नक्शा), 3 वर्णों के लिए अप्रयुक्त था।

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

यहाँ मेरा एल्गोरिथ्म अब तक, आलोचना करने के लिए स्वतंत्र है।

foreach (Block in level)
{
    if (distance from block to player > a specified amount)
        ignore this block;
    else
    {
        get the intersection depth between the two bounding boxes
        if (depth of intersection != Zero-vector)
        {
            check y size vs x size
            resolve on smallest axis
        }
    }
}

जैसा कि आप ध्यान देंगे, जब स्तर का आकार बड़ा हो जाता है, तो इस एल्गोरिथ्म का क्रम एन ब्लॉकों द्वारा बढ़ता है। मैं उन ब्लॉकों पर भी विचार नहीं करना चाहूंगा जो खिलाड़ी के पास भी नहीं हैं।

मैं सोच रहा हूं कि शायद (0,0) (मेपविदथ, मैपहाइट) का उपयोग सूची के बजाय ब्लॉक के दोहरे-सरणी, व्यक्ति की स्थिति के आधार पर एक खतरे-क्षेत्र की गणना करते हुए जैसे, यदि खिलाड़ी की स्थिति 10 (20) है यह (0, 10) से (20, 30), या इतने पर दिखेगा।

किसी भी विचार और विचार भयानक हैं, धन्यवाद।


1
और स्टेक्सचेंज में आपका स्वागत है! :-) यदि आप इस बात से अनजान नहीं हैं कि यदि आप इस बात से अनजान हैं कि संपूर्ण QA और प्रतिष्ठा प्रणाली कैसे काम करती है।
डेविड गौवेया

निश्चित रूप से ये टाइलें 16 गुणा 16 पिक्सल, 1920 से 1080 तक 8,100 टाइलों से बड़ी हैं। निश्चित रूप से आप जानते हैं कि जंगम संस्थाएं कहां हैं, और आप केवल ग्रिड पर टाइलें देख सकते हैं जो संभवतः सीमा में हो सकती हैं (यदि कोई 160 * 160 है और केंद्र टाइल में है (12,12) तो आपको केवल टाइलों के बीच जांच की आवश्यकता है (6) , 6) और (18,18) कुल ~ 150 संभावित टाइलों के लिए।) निश्चित रूप से गुरुत्वाकर्षण के तहत टाइलें केवल नीचे गिरती हैं, और इसलिए आपको केवल इसके नीचे की अगली टाइल की तलाश करनी चाहिए।
DampeS8N

क्या आपको लगता है कि 16x16 बहुत छोटा है? टाइलों के आकार को बदलना मेरे लिए कठिन नहीं होगा, क्योंकि कुछ भी जो संदर्भ टिल्विडथ / ऊंचाई एक स्थिर स्थिर है। मुझे बस इतना करना होगा कि उन्हें पेंट.नेट में बड़ा कर दिया जाए, जो अच्छा है क्योंकि यह अधिक विवरण जोड़ता है।
रॉस

क्या आप अपने टक्कर कोड को साझा करना चाहेंगे? : /
ashes999

जवाबों:


7

जी हां, आप सही सोच रहे हैं। आपको टाइलों के 2D सरणी का उपयोग करना चाहिए क्योंकि यह आपको स्थिति के अनुसार टाइलों को अनुक्रमित करने की अनुमति देता है।

Block[,] level = new Block[width, height];

और चूंकि खिलाड़ी केवल अपने आस-पास की टाइलों से टकरा सकता है, इसलिए आपके द्वारा किए जाने वाले टक्कर की संख्या बहुत कम है। यह निश्चित रूप से खिलाड़ी के आकार पर निर्भर करता है। Platformer नमूना इस तरह यह करता है:

int leftTile = (int)Math.Floor((float)characterBounds.Left / tileWidth);
int rightTile = (int)Math.Ceiling(((float)characterBounds.Right / tileWidth)) - 1;
int topTile = (int)Math.Floor((float)characterBounds.Top / tileHeight);
int bottomTile = (int)Math.Ceiling(((float)characterBounds.Bottom / tileHeight)) - 1;

for (int y = topTile; y <= bottomTile; ++y)
{
    for (int x = leftTile; x <= rightTile; ++x)
    {
        // Handle collisions with the tile level[x,y] just like you were doing!
    }
}

यदि आपको अभी भी कोई समस्या है तो नमूने की जाँच करें।


यह एक बहुत अच्छा सा एल्गोरिथ्म है, मैंने प्लेटफ़ॉर्मर नमूने के बारे में भी नहीं सुना था (मुझे होना चाहिए, लेकिन मैं अज्ञानता का दावा करता हूं)। धन्यवाद!
रॉस

@ सच? आपको आश्चर्य होगा कि आपका समाधान नमूने के समान कैसे है। :-) सूची भाग को माइनस करें, बाकी सब कुछ बहुत समान है (इंटरसेक्ट बाउंडिंग बॉक्स, चौराहे की गहराई प्राप्त करें, सबसे छोटी धुरी पर हल करें)।
डेविड गौवेया

1
अरे यार, मैंने अभी देखा। >। <काश मुझे यह 2 दिन पहले पता होता !! ठीक है, मैं XNA में नया हूं, लेकिन मैंने 2 डी ग्राफिक्स (सिर्फ ओपनजीएल, बहुत गेम प्रोग्रामिंग नहीं) के साथ डील किया है। मुझे लगता है कि मुझे पहले और अधिक संसाधनों की जांच करनी चाहिए, इससे पहले कि मैं कोडिंग में सिर-पहले जाऊं।
रॉस

1

मुझे लगता है कि मेरा जवाब आपका जवाब होगा! ;-)

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

शायद riemers.net पर टकराव पर ट्यूटोरियल की जाँच करें यदि आपके पास पहले से नहीं है।


मैंने रीमर के बारे में सुना है, लेकिन कभी भी देखने के लिए नहीं मिला, धन्यवाद!
रॉस

1

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

चूंकि टाइलें स्थिर हैं, इसलिए मैं क्वाडट्री का उपयोग करने का सुझाव दूंगा। एक क्वाड ट्री क्वाड्स से बना है। प्रत्येक क्वाड चार आयतों से बना होता है और उनमें से प्रत्येक आयत क्वाड होता है। यह एक निर्दिष्ट आकार तक पुनरावृत्ति जारी रखता है। प्रत्येक क्वाड में टाइल्स की एक सूची हो सकती है जो स्क्रीन के उस क्षेत्र में निवास करती है। इस तरह, जब आप टकराव के लिए जाँच कर रहे हैं आप कर सकते हैं

  1. तत्काल आसपास के क्षेत्र में उन लोगों के लिए चेक को प्रतिबंधित करें
  2. जाँच केवल उन वस्तुओं पर रोकें जो चलती हैं

अब अगर आप टाइल्स ऑफ स्क्रीन भी नहीं देखना चाहते हैं तो आप कुछ ऐसा कर सकते हैं

public bool CheckCollision(myPosition) {
    if(quadNodes.Count > 0) {
        // This is not a leaf, keep checking
        foreach(Quad node in quadNodes) {
            if(node.Position is insideViewport && nearPlayer)
                // Continue recursion
            }
        }
    }
    else {
        // This is a leaf, do checks
        foreach(Tile tile in tileList) {
            if(collision)
                return true;
        }
        return false;
    }
}

हम्म, मैंने 3 डी टक्कर का पता लगाने में ऑक्ट्रेसेस के बारे में सुना है, लेकिन 2 डी टक्कर का पता लगाने के लिए उन्नत डेटा संरचना का उपयोग नहीं किया गया है। आपका बहुत बहुत धन्यवाद!
रॉस

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

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

1
यही मैं सुझाव देने वाला था :) इलाके के साथ टकरावों को संभालने के लिए ग्रिड का उपयोग किया जाना चाहिए, जबकि अंतर-वस्तु टकराव को संभालने के लिए एक क्वाडट्री का उपयोग किया जा सकता है।
डेविड गौवेया

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