पूरे नक्शा डिजाइन बनाम टाइलों की सरणी डिजाइन


11

मैं एक 2D आरपीजी पर काम कर रहा हूं, जिसमें सामान्य कालकोठरी / शहर के नक्शे (पूर्व-उत्पन्न) की सुविधा होगी।

मैं टाइल्स का उपयोग कर रहा हूं, कि मैं फिर नक्शे बनाने के लिए गठबंधन करूंगा। मेरी मूल योजना फ़ोटोशॉप, या कुछ अन्य ग्राफिक प्रोग्राम का उपयोग करके टाइलों को इकट्ठा करने की थी, जिसमें एक बड़ी तस्वीर थी जिसे मैं मानचित्र के रूप में उपयोग कर सकता था।

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

सबसे आम तरीका क्या है, और प्रत्येक के फायदे / नुकसान क्या हैं?


1
मुख्य मुद्दा स्मृति है। एक बनावट जो एक 1080p स्क्रीन को एक बार भरती है वह लगभग 60mb है। इसलिए एक छवि प्रति पिक्सेल एक इंट का उपयोग करती है, एक टाइल एक इंट प्रति पिक्सेल (पिक्सेल / * टाइलाइज़) का उपयोग करती है। इसलिए यदि टाइलें 32,32 हैं, तो आप एक पिक्सेल बनाम टाइल का उपयोग करके 1024 गुना बड़े मानचित्र का प्रतिनिधित्व कर सकते हैं। इसके अलावा बनावट की अदला
बदली

जवाबों:


19

सबसे पहले, मुझे कहना है कि 2D आरपीजी मेरे दिल के पास और प्यारे हैं और पुराने DX7 VB6 MORPG इंजन के साथ काम कर रहे हैं (हंसो मत, यह 8 साल पहले था, अब :-)) क्या मुझे पहले खेल के विकास में दिलचस्पी है । हाल ही में, मैंने XNA का उपयोग करने के लिए उन इंजनों में से एक में काम करने वाले खेल को बदलना शुरू किया।

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

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

  1. पहली चीज जो आपको करने की ज़रूरत है वह एक टाइलशीट बनाना है। यह सिर्फ एक बड़ी छवि है जिसमें आपकी सभी टाइलें ग्रिड में संरेखित हैं। यह (और शायद टाइल्स की संख्या के आधार पर एक अतिरिक्त) केवल एक चीज होगी जिसे आपको लोड करने की आवश्यकता है। सिर्फ 1 छवि! आप खेल में हर टाइल के साथ 1 प्रति नक्शा या एक लोड कर सकते हैं; जो भी संगठन आपके लिए काम करता है।
  2. अगला, आपको यह समझने की आवश्यकता है कि आप उस "शीट" को कैसे ले सकते हैं और प्रत्येक टाइल को एक संख्या में अनुवाद कर सकते हैं। यह कुछ सरल गणित के साथ बहुत सीधा है। ध्यान दें कि यहाँ विभाजन पूर्णांक विभाजन है , इसलिए दशमलव स्थानों को गिरा दिया जाता है (या यदि आप चाहें तो इसे नीचे किया जा सकता है)। निर्देशांक और वापस करने के लिए कोशिकाओं को कैसे परिवर्तित करें।
  3. ठीक है, अब जब आपने टाइल्सशीट को कोशिकाओं (संख्याओं) की एक श्रृंखला में तोड़ दिया है, तो आप उन नंबरों को ले सकते हैं और आपको जो भी कंटेनर पसंद है, उसमें प्लग कर सकते हैं। सादगी के लिए, आप बस एक 2 डी सरणी का उपयोग कर सकते हैं।

    int[,] mapTiles = new int[100,100]; //Map is 100x100 tiles without much overhead
  4. अगला, आप उन्हें आकर्षित करना चाहते हैं। उन तरीकों में से एक जो आप इसे बहुत अधिक कुशल बना सकते हैं (मानचित्र आकार के आधार पर) केवल उन कोशिकाओं की गणना करना है जो कैमरा वर्तमान में देख रहा है और उन के माध्यम से लूप करता है। आप ऐसा कैमरा के ऊपरी-बाएँ ( tl) और नीचे-दाएं ( br) कोनों के मानचित्र टाइल सरणी निर्देशांक को प्राप्त करके कर सकते हैं । फिर लूप से tl.X to br.Xऔर, एक नेस्टेड लूप में, tl.Y to br.Yउन्हें खींचने के लिए। नीचे उदाहरण कोड:

    for (int x = tl.X; x <= br.X;x++) {
        for (int y = tl.Y; y <= br.Y;y++) {
            //Assuming tileset setup from image
            Vector2 tilesetCoordinate = new Vector2((mapTiles[x,y] % 8) * 32,(mapTiles[x,y] / 8) * 32);
            //Draw 32x32 tile using tilesetCoordinate as the source x,y
        }
    }
  5. जैकपॉट! यह टाइल इंजन की मूल बातें है। आप देख सकते हैं कि 1000x1000 का मैप होना बहुत आसान है, जिसमें ज्यादा ओवरहेड नहीं है। इसके अलावा, यदि आपके पास 255 से कम टाइलें हैं, तो आप प्रति सेल 3 बाइट्स द्वारा मेमोरी को काटने के लिए बाइट सरणी का उपयोग कर सकते हैं। यदि एक बाइट बहुत छोटा है, तो एक सूदखोर शायद आपकी जरूरतों के लिए पर्याप्त होगा।

नोट: मैंने दुनिया के निर्देशांक की अवधारणा को छोड़ दिया (जो कि आपके कैमरे की स्थिति पर आधारित होगा) उसके बाद से, मुझे लगता है, इस उत्तर के दायरे से बाहर है। आप GameDev.SE पर यहाँ उस पर पढ़ सकते हैं।

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

  • इस सवाल का मेरा जवाब यह बताता है कि मैं अपने खेल में मैप सेल्स और लेयरिंग को कैसे हैंडल करता हूँ। (तीसरा लिंक देखें।)
  • इस सवाल का मेरा जवाब बताता है कि मैं डेटा को बाइनरी प्रारूप में कैसे संग्रहीत करता हूं।
  • यह पहला (अच्छा, तकनीकी रूप से दूसरा, लेकिन पहला "तकनीकी") ब्लॉग पोस्ट है जिस खेल के विकास के बारे में मैं काम कर रहा था। पूरी श्रृंखला में पिक्सेल शेड्स, प्रकाश व्यवस्था, टाइल व्यवहार, आंदोलन और उस सभी मज़ेदार सामान जैसी चीजों के बारे में जानकारी है। मैंने वास्तव में अपने उत्तर की सामग्री को मेरे द्वारा ऊपर पोस्ट की गई पहली लिंक में शामिल करने के लिए अपडेट किया है, इसलिए आप इसके बजाय इसे पढ़ना चाह सकते हैं (मैंने चीजें जोड़ ली हैं)। यदि आपके कोई प्रश्न हैं, तो आप वहाँ या यहाँ एक टिप्पणी छोड़ सकते हैं और मुझे मदद करने में खुशी होगी।

अन्य टाइल-इंजन संसाधन

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

वाओ, मैंने जो पूछा है, उससे दोगुना अधिक जानकारी और बहुत सारे सवालों के जवाब मैंने नहीं पूछे, बहुत बहुत धन्यवाद :)
Cristol.GdM

@ मिकलिचोव - खुशी है कि मैं मदद कर सकता हूँ! :)
रिचर्ड मार्स्केल - Drackir

आमतौर पर एक 2D सरणी के साथ आप अपने Y के रूप में पहला आयाम और अपने X के रूप में अगला उपयोग करना चाहते हैं। स्मृति में एक सरणी क्रमिक रूप से 0,0-i तो 1,0-i होने जा रही है। यदि आप एक्स पहली मुर्गी के साथ नेस्टेड छोरों करते हैं तो आप वास्तव में पढ़ने के क्रमिक मार्ग का अनुसरण करने के बजाय स्मृति में आगे और पीछे कूद रहे हैं। हमेशा (y) तो (x) के लिए।
ब्रेट डब्ल्यू

@BrettW - एक वैध बिंदु। धन्यवाद। यह मुझे आश्चर्यचकित करता है कि 2 जी सरणियों को .Net (पंक्ति-प्रमुख क्रम) में कैसे संग्रहीत किया जाता है। आज कुछ नया सीखा है! :-))। हालाँकि, अपने कोड को अपडेट करने के बाद, मैंने महसूस किया कि यह बिल्कुल वैसा ही है जैसा आप वर्णन कर रहे हैं, बस चरों के साथ। अंतर यह है कि किस क्रम में टाइलें खींची जाती हैं। मेरा वर्तमान उदाहरण कोड ऊपर-से-नीचे, बाएँ-से-दाएँ खींचता है जबकि आप जो वर्णन करते हैं वह बाएँ-से-दाएँ, शीर्ष-से-नीचे की ओर आकर्षित होता है। इसलिए, सादगी के लिए, मैंने इसे वापस मूल में बदलने का फैसला किया। :-)
रिचर्ड मार्स्केल - Drackir

6

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

कहा जा रहा है कि दोनों प्रणालियों को अलग-अलग, या एक साथ भी इस्तेमाल किया जा सकता है।

एक मानक टाइल आधारित प्रणाली में निम्नलिखित ताकतें हैं:

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

टाइल्स का नुकसान यह है कि आपको इस टाइल आधारित डेटा के निर्माण के लिए एक सिस्टम बनाना होगा। आप एक छवि बना सकते हैं जो प्रत्येक पिक्सेल को एक टाइल के रूप में उपयोग करता है, इस प्रकार एक बनावट से अपने 2 डी सरणी का निर्माण करता है। आप एक स्वामित्व प्रारूप भी बना सकते हैं। बिटफ्लैग का उपयोग करके आप प्रति टाइल की एक बड़ी संख्या को काफी कम जगह में स्टोर कर सकते हैं।

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

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

कोड उदाहरण प्रदान करने के लिए आपको अपने वातावरण / इंजन / भाषा पर अधिक विवरण प्रदान करने की आवश्यकता होगी।


धन्यवाद! मैं C # के तहत काम कर रहा हूं, और अंतिम काल्पनिक 6 (या मूल रूप से सबसे स्क्वायर एसएनईएस आरपीजी) के समान (लेकिन कम प्रतिभाशाली) संस्करण के लिए जा रहा हूं, इसलिए फर्श टाइल्स और संरचना टाइल (यानी घर)। मेरी सबसे बड़ी चिंता यह है कि मैं यह नहीं देखता कि 2 डी सरणी का निर्माण बिना घंटे बिताए कैसे हो सकता है "वहाँ एक घास का कोना है, तो तीन सीधे क्षैतिज, फिर एक घर का कोना, फिर ..", साथ में संभव गलतियों के टन के साथ। मार्ग।
२.२० बजे क्रिस्टोल.जीडीएम

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

3

नक्शा खींचना: इंजन पर टाइलें आसान हैं, क्योंकि तब नक्शे को टाइल सूचकांकों के विशालकाय सरणी के रूप में दर्शाया जा सकता है। ड्रा कोड सिर्फ एक नेस्टेड लूप है:

for i from min_x to max_x:
    for j from min_y to max_y:
        Draw(Tiles[i][j], getPosition(i,j))

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

उदाहरण के लिए, टकराव के लिए टाइल की जानकारी का पुन: उपयोग करना भी आसान है। उदाहरण के लिए, पात्र के स्प्राइट के ऊपरी-बाएँ कोने में इलाके की टाइल पाने के लिए:

let x,y = character.position
let i,j = getTileIndex(x,y) // <- getTileIndex is the opposite function of getPosition
let tile = Tiles[i][j]

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

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