तेजी से 2 डी टकराव का पता लगाने


13

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

Enemy class update method
    Loop through all enemies (continue; if the loop points at this object)
        If enemy object intersects with this object
            Push enemy object away from this enemy object

यह ठीक काम करता है। जब तक मेरे पास केवल <200 दुश्मन इकाइयाँ हैं। जब मैं 300-350 शत्रु संस्थाओं के करीब पहुँचता हूँ तो मेरी फ्रेम दर में भारी गिरावट आने लगती है। पहले मुझे लगा कि यह खराब प्रतिपादन है इसलिए मैंने उनका ड्रॉ कॉल हटा दिया। इससे मुझे बिल्कुल भी मदद नहीं मिली, मुझे एहसास हुआ कि यह अद्यतन पद्धति थी। उनकी अद्यतन पद्धति में एकमात्र भारी हिस्सा यह प्रत्येक दुश्मन-छोर-थ्रू-हर-दुश्मन भाग है। जब मैं 300 शत्रुओं के करीब पहुँचता हूँ तो खेल 90000 (300x300) कदम की पुनरावृत्ति करता है। मेरा ~

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

tl; डॉ? मैं संस्थाओं के बीच टकराव का पता कैसे लगा सकता हूं?

त्वरित संपादन: यदि यह किसी भी मदद के लिए है, तो मैं C # XNA का उपयोग कर रहा हूं।


मैं सोच रहा हूं कि आपको पहली बार में 90K में जाने के लिए कैसे मिला। 20K में मेरा चोक (हालांकि मैं पूर्ण SAT MTV डिटेक्शन कर रहा हूं)। लेकिन मैं सभी दुश्मनों के माध्यम से पाला मारता हूं जो कि संभव है। हालांकि आपको जो करने की आवश्यकता है वह यह है कि अगर उन्हें पहले ही जाँच लिया जा चुका है, क्योंकि अगर आप जैसा कहते हैं, वैसा ही करते हैं, तो हर किसी का हर किसी के साथ दो बार परीक्षण हो रहा है।
प्रलयकाल तर्क


इस सवाल का बहुत अच्छा जवाब है कि @MarkusvonBroady ने लिंक किया है।
साइफ्रे

जवाबों:


11

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

मैं आमतौर पर इस तरह के सिस्टम के लिए तीन संग्रह करता हूं। और जब आप उन संस्थाओं की संख्या के बारे में बात कर रहे हैं जिन्हें आप लक्ष्य कर रहे हैं, तो आपको इसके लिए पूर्ण विकसित दृश्य ग्राफ के साथ जाने की आवश्यकता हो सकती है क्योंकि ट्रैकिंग डेटा (प्रत्येक इकाई की प्रविष्टि के साथ प्रति इकाई 3 सूची) जल्दी से बाहर निकल सकते हैं नियंत्रण का।

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

अगली सूची वे हैं जो एक बफर रेंज में होंगी जो बहुत अधिक प्रयास के साथ इकाई की सीमा में स्थानांतरित हो सकती हैं .. हम तर्क के लिए इस सीमा को X * 1.5 कहेंगे। यह एक समय की कटा हुआ सूची है, जहाँ आप केवल प्रति फ्रेम में उनमें से कुछ को अपडेट करेंगे, लेकिन यह सुनिश्चित करेंगे कि आप आसानी से काम कर रहे चीजों की उपस्थिति को बनाए रखने के लिए पर्याप्त तेजी से गुजर रहे हैं।

तीसरी सूची 'सब कुछ' की सूची है और इससे बचने का एक तरीका यह हो सकता है, जबकि यह हो सकता है (संपूर्ण निकाय सूची को स्कैन करना और शायद यह देखने के लिए कि क्या प्रगति करने से पहले अन्य सूचियों में से एक है? काम कर सकता है, या यह चीजों को बहुत खराब कर सकता है।) इस सूची में वस्तुओं को कम से कम जांचा जाता है क्योंकि इसे निश्चित रूप से अन्य दो सूचियों में से एक में रखे जाने के लिए कुछ फ्रेम से अधिक लेना चाहिए।

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

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

उम्मीद है की यह मदद करेगा।


1
यह एक अस्पष्ट जवाब है। और क्या हम कुछ टकराव को स्वीकार करना स्वीकार कर सकते हैं ?? बहुत सरल, एक डेटा संरचना का उपयोग करें जो आपके लिए सतह विभाजन का काम करेगा, जैसे कि क्वाड ट्री मैं यहां बात करता हूं। यहां तक ​​कि एक ट्रैक्टर ट्री को ओवरहेड से बचने के लिए थोड़ा ठीक ट्यूनिंग की आवश्यकता होती है, इसलिए मैं उस 'समाधान' की जटिलता की कल्पना नहीं कर सकता हूं जिसके बारे में आप बात करते हैं। बुनियादी प्रोग्रामिंग नियम: बस सही डेटा संरचना का उपयोग करें।
GameAlchemist

@VincentPiel एक दृश्य ग्राफ एक चौकोर पेड़ से अधिक जटिल नहीं है।
साइपर

@ नाम: जाहिर है कि यह अधिक जटिल है। यदि आप QuadTree की पूरी गति को समझने में कोई आपत्ति नहीं करते हैं, तो आप नेट पर एक QuadTree lib प्राप्त कर सकते हैं और कुछ घंटों में पूरी तरह से काम कर सकते हैं। जैसे कोई सवाल नहीं: मैं पहली सूची में क्या डालूं, दूसरा, तीसरा, मैं किसी अन्य सूची में एक इकाई कैसे तय करूं ... और कोई टकराव नहीं हुआ। जब आपके पास कार हो सकती है तो बाइक का उपयोग क्यों करें?
गेमअल्केमिस्ट

@VincentPiel मुझे लगता है कि आप यहाँ मेरे बजाय Cypher को अपनी टिप्पणी का मतलब है। Anywho एक क्वाड ट्री सिर्फ एक प्रकार का दृश्य ग्राफ है और आपको याद रखना होगा कि आप प्रति सेकंड X फ्रेम पर चल रहे हैं। यदि आप छूटे हुए टकरावों को नोटिस कर रहे हैं, तो आपको बेहतर चीजों को संतुलित करने के लिए अपनी सीमा सीमा को समायोजित करने की आवश्यकता है। मेरा समाधान केवल यह सुनिश्चित करने का एक बहुत ही सरल तरीका है कि आप केवल हर फ्रेम की चीजों की जांच करें जिनके साथ टकराए जाने की संभावना है और फिर बाकी को पृष्ठभूमि / सीमित अपडेट करने के लिए यह देखने के लिए कि क्या वे उच्च प्राथमिकता के लिए योग्य हैं।
जेम्स

6

आपको सॉर्ट किए गए डेटा संरचना के साथ टकराव को संभालना है, इसलिए आप भयानक n ^ 2 के बजाय n * लॉग (n) बार कर सकते हैं। और n * log (n) लगभग रैखिक है जैसा कि आप जानते हैं। एक (शास्त्रीय) उदाहरण एक क्वाडट्री है, यहां ग्राफिक्स और कोड (जावा) के साथ एक बहुत ही सरल और अच्छी तरह से लिखा ट्यूटोरियल है:

http://gamedev.tutsplus.com/tutorials/implementation/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space/

Rq: किसी भी भाषा में QuadTrees के लिए एक कार्यान्वयन खोजना काफी आसान है। फिर भी, आपको पेड़ के लिए सही 'ग्रैन्युलैरिटी' के बारे में सोचना होगा, और पेड़ का आकार जितना बड़ा होगा, हमारे पास उतना ही अधिक होगा जो एक नोड के अंदर फिट नहीं होता है। Rq3: एक बार जब आप अपने पेड़, स्क्रीन और संस्थाओं के बीच एक 'टकराव' आपको दे ... दृश्यमान इकाइयां !! एक समय में अधिक लॉग (n) की तरह, तो क्यों नहीं n बड़ा है? (सबसे खराब स्थिति स्पष्ट रूप से इस दृष्टिकोण के लिए n में एक समय है।)
Rq 2: चूँकि आपका अंतरिक्ष विभाजन केवल टकराव का पता लगाने के लिए किया जाता है, आपको अपनी पसंद के अनुसार अंतरिक्ष को विभाजित करने की पूर्ण स्वतंत्रता है। उदाहरण के लिए, मैं चार ईगल भागों में विभाजित नहीं होता, बल्कि मैं नए विभाजन के लिए केंद्र के रूप में वर्तमान स्तर के बारिकेटर का उपयोग करता हूं। 1) एल्गोरिथ्म अभी भी n * लॉग (n) है, 2) यदि आप पेड़ से बाहर के दृश्य को algorithm पुनर्निर्माण ’करने की संभावना को ढीला करते हैं -लेकिन आप परवाह नहीं करते हैं- और 3) आपके पास बहुत अधिक संतुलित पेड़ है, कम उपरि ।


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

0

बाइनरी स्पेस पार्टीशन ट्री, क्वाड्रीट्री, ऑक्ट्री (3 डी के लिए) संभव पेड़ हैं जो आप उत्पन्न कर सकते हैं (या बनाए रख सकते हैं, अगर आप महत्वाकांक्षी हैं) तो हर उस वस्तु को अपडेट करें, जिस पर आप आवेदन करना चाहते हैं।


3
यह टिप्पणी करने के लिए अधिक उपयुक्त है। अपने उत्तर में अधिक जोड़ने पर विचार करें।

0

मैं काफी भोली हूँ जब बात क्वाड या ऑक्टो ट्री की आती है। लेकिन मुझे लगता है कि इस विधि को करना चाहिए:

आपको खिलाड़ी संरचना / वर्ग को संशोधित करना होगा। अन्य प्लेयर संरचना में पॉइंटर्स की एक सरणी / वेक्टर जोड़ें।

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

अब केवल एक दूसरे की सूची में खिलाड़ियों के बीच टकराव की जाँच करें।

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