वे इसे कैसे करेंगे: टेरारिया में लाखों टाइलें


45

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

अपडेट : कोड यह दिखाने के लिए जोड़ा गया है कि मैं चीजों को कैसे करता हूं।

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

...
    public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
    {
        foreach (Tile tile in this.Tiles)
        {
            if (tile != null)
            {
                if (tile.Position.X < -this.Offset.X + 32)
                    continue;
                if (tile.Position.X > -this.Offset.X + 1024 - 48)
                    continue;
                if (tile.Position.Y < -this.Offset.Y + 32)
                    continue;
                if (tile.Position.Y > -this.Offset.Y + 768 - 48)
                    continue;
                tile.Draw(spriteBatch, gameTime);
            }
        }
    }
...

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

...
    public virtual void Draw(SpriteBatch spriteBatch, GameTime gameTime)
    {
        if (this.type == TileType.TileSet)
        {
            spriteBatch.Draw(this.texture, this.realm.Offset + this.Position, texture_tl, this.BlendColor);
            spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(8, 0), texture_tr, this.BlendColor);
            spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(0, 8), texture_bl, this.BlendColor);
            spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(8, 8), texture_br, this.BlendColor);
        }
    }
...

मेरे कोड में किसी भी आलोचना या सुझाव का स्वागत है।

अद्यतन : समाधान जोड़ा गया।

यहाँ अंतिम Level.Draw विधि है। Level.TileAt विधि केवल इनपुट किए गए मानों की जांच करती है, OutOfRange अपवादों से बचने के लिए।

...
    public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
    {
        Int32 startx = (Int32)Math.Floor((-this.Offset.X - 32) / 16);
        Int32 endx = (Int32)Math.Ceiling((-this.Offset.X + 1024 + 32) / 16);
        Int32 starty = (Int32)Math.Floor((-this.Offset.Y - 32) / 16);
        Int32 endy = (Int32)Math.Ceiling((-this.Offset.Y + 768 + 32) / 16);

        for (Int32 x = startx; x < endx; x += 1)
        {
            for (Int32 y = starty; y < endy; y += 1)
            {
                Tile tile = this.TileAt(x, y);
                if (tile != null)
                    tile.Draw(spriteBatch, gameTime);

            }
        }
    }
...

2
क्या आप पूरी तरह से सकारात्मक हैं कि आप केवल कैमरे के दृष्टिकोण में प्रतिपादन कर रहे हैं, इसका अर्थ यह है कि सही निर्धारण के लिए कोड क्या है?
कूपर

5
फ्रैमेरेट 60 से 20 एफपीएस से गिरता है, सिर्फ आवंटित मेमोरी के कारण? यह बहुत संभावना नहीं है, कुछ गलत होना चाहिए। यह किस मंच पर है? क्या सिस्टम डिस्क को वर्चुअल मेमोरी स्वैप कर रहा है?
माईक सेमर

6
@Drackir इस मामले में मैं कहूंगा कि अगर कोई टाइल वर्ग है, तो उपयुक्त लंबाई वाले पूर्णांक की एक सरणी होनी चाहिए, और जब डेढ़ लाख ऑब्जेक्ट हों, तो OO ओवरहेड कोई मज़ाक नहीं है। मुझे लगता है कि वस्तुओं के साथ ऐसा करना संभव है, लेकिन बिंदु क्या होगा? एक पूर्णांक सरणी को संभालना आसान है।
१४:१५

3
आउच! पुनरावृत्ति सभी टाइल्स और हर एक को ध्यान में रखते हुए कि पर चार बार ड्रा बुला। यहाँ निश्चित रूप से कुछ सुधार संभव है ....
थेडियन

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

जवाबों:


56

क्या आप सभी 500,000 टाइलों के माध्यम से लूप कर रहे हैं जब आप प्रतिपादन कर रहे हैं? यदि हां, तो यह आपकी समस्याओं का हिस्सा होने की संभावना है। यदि आप रेंडर करते समय आधा मिलियन टाइलों के माध्यम से लूप करते हैं, और उन पर 'अपडेट' टिक करते समय आधा मिलियन टाइलें लगाते हैं, तो आप प्रत्येक फ्रेम में एक मिलियन टाइलों के बावजूद लूप कर रहे हैं।

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

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

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

(जाहिर है, अगर आपका इंजन टाइलों पर किसी भी प्रकार का अपडेट टिक नहीं करता है, तो आप इस उत्तर के भाग को अनदेखा कर सकते हैं जिसमें उन का उल्लेख है।)


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

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

2
@MindWorX: जब यह पुनः लोड होता है तो सभी अपडेट करना हमेशा काम नहीं करेगा - मान लीजिए आपके पास बंजर क्षेत्र और फिर घास का एक पूरा गुच्छा है। तुम युगों तक चले जाओ और फिर घास की ओर चलो। जब घास के साथ ब्लॉक इसे पकड़ता है और यह उस ब्लॉक में फैलता है, लेकिन यह पहले से लोड किए गए नजदीकी ब्लॉकों में नहीं फैलता है। इस तरह की चीजें खेल की तुलना में बहुत धीमी गति से आगे बढ़ती हैं , हालांकि - किसी भी एक अपडेट चक्र में टाइल्स की केवल एक छोटी उपसमूह की जांच करें और आप सिस्टम को लोड किए बिना दूर के इलाके को लाइव कर सकते हैं।
लॉरेन Pechtel

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

1
किसी के लिए भी, टेरारिया अपने पूरे टाइल डेटा को 2d सरणी (अधिकतम आकार 8400x2400) में संग्रहीत करता है। और फिर यह तय करने के लिए कुछ सरल गणित का उपयोग करता है कि टाइल के किस अनुभाग को प्रस्तुत करना है।
२०:५० पर फ्रेंचएनजेड

4

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

आपको केवल प्रक्रिया करने के लिए आवश्यक व्हाट्स पर पुनरावृति करनी चाहिए। इसलिए सोचें कि आपको वास्तव में टाइल्स की क्या जरूरत है। आकर्षित करने के लिए आपको केवल एक बनावट की आवश्यकता होती है, लेकिन आप एक वास्तविक छवि पर पुनरावृत्ति नहीं करना चाहते क्योंकि वे प्रक्रिया के लिए बड़े हैं। आप सिर्फ एक int [,] या यहां तक ​​कि एक अहस्ताक्षरित बाइट [,] बना सकते हैं (यदि आप अधिक उम्मीद नहीं करते हैं तो 255 टाइल बनावट)। आपको बस इन छोटे सरणियों पर पुनरावृत्त करना है और बनावट खींचने के लिए एक स्विच या यदि कथन का उपयोग करना है।

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

struct TileUpdate
{
public byte health;
public byte type;
public byte damage;
}

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

यदि आप उपरोक्त संरचना रखते हैं तो यह केवल 3 बाइट्स प्रति टाइल लेता है। तो बचत और स्मृति उद्देश्य के लिए यह आदर्श है। प्रसंस्करण की गति के लिए यह वास्तव में मायने नहीं रखता है यदि आप इंट या बाइट का उपयोग करते हैं, या यहां तक ​​कि लंबे समय तक इंट का उपयोग करें यदि आपके पास 64 बिट सिस्टम है।


1
हाँ, बाद में मेरे इंजन की पुनरावृत्तियों का उपयोग करने के लिए विकसित हुआ। ज्यादातर स्मृति की खपत को कम करने और गति बढ़ाने के लिए। ByRef प्रकार एक सरणी की तुलना में धीमे होते हैं, जो कि ByVal स्ट्रक्चर्स से भरे होते हैं। फिर भी यह अच्छा है कि आपने इसे उत्तर में जोड़ा है।
विलियम मारीगर

1
कुछ यादृच्छिक एल्गोरिदम की तलाश करते हुए हाँ इस पर ठोकर खाई। तुरंत आपने अपने कोड में अपने स्वयं के टाइल वर्ग का उपयोग करते हुए देखा। यह बहुत आम गलती है जब आपका नया। यह देखकर अच्छा लगा कि आप 2 साल पहले इस पोस्ट को सक्रिय कर चुके हैं।
Madmenyo

3
आप या तो ज़रूरत नहीं है healthया damage। आप सबसे हाल ही में उठाए गए टाइल स्थानों और प्रत्येक पर नुकसान का एक छोटा बफर रख सकते हैं। यदि कोई नया टाइल उठाया गया है और बफर भरा हुआ है तो नया जोड़ने से पहले उसमें से सबसे पुराने स्थान को रोल करें। यह आपको एक समय में कितने टाइलों तक सीमित कर सकता है लेकिन इस पर वैसे भी (लगभग #players * pick_tile_size) एक आंतरिक सीमा है । यदि आप इसे आसान बनाते हैं तो आप इस सूची को प्रति खिलाड़ी रख सकते हैं। गति के लिए आकार मायने रखता है; छोटे आकार का अर्थ है प्रत्येक CPU कैशलाइन में अधिक टाइलें।
सीन मिडिलिचच

@SeanMiddleditch आप सही हैं लेकिन वह बात नहीं थी। मुद्दा यह था कि आप रुकें और सोचें कि आपको वास्तव में स्क्रीन पर टाइल खींचने और अपनी गणना करने की आवश्यकता है। चूंकि ओपी एक पूरी कक्षा का उपयोग कर रहा था इसलिए मैंने एक सरल उदाहरण बनाया, एक सीखने की प्रगति में सरल एक लंबा रास्ता तय करता है। अब कृपया पिक्सेल घनत्व के लिए मेरे विषय को अनलॉक करें, आप स्पष्ट रूप से एक प्रोग्रामर एक सीजी कलाकार की आंखों से उस प्रश्न को देखने की कोशिश करेंगे। चूँकि यह साइट गेम्स गेम्स के लिए CG के लिए भी है।
मद्मान्यो

2

विभिन्न एन्कोडिंग तकनीकें हैं जिनका आप उपयोग कर सकते हैं।

RLE: तो आप एक निर्देशांक (x, y) से शुरू करते हैं और फिर गिनते हैं कि एक ही अक्ष के साथ एक ही टाइल के कितने साइड-बाय-साइड (लंबाई) मौजूद हैं। उदाहरण: (1,1,10,5) का अर्थ होगा कि 1,1 से समन्वय करना शुरू करने पर टाइल के प्रकार 5 के किनारे-किनारे 10 टाइलें हैं।

विशाल सरणी (बिटमैप): सरणी का प्रत्येक तत्व उस क्षेत्र में रहने वाले टाइल प्रकार पर रहता है।

संपादित करें: मैं अभी यहाँ इस उत्कृष्ट सवाल पर आया था: मैप पीढ़ी के लिए रैंडम सीड फंक्शन?

Perlin शोर जनरेटर एक अच्छा जवाब की तरह लग रहा है।


मुझे यकीन नहीं है कि आप उस प्रश्न का उत्तर दे रहे हैं जो आपसे पूछा जा रहा है, क्योंकि आप एन्कोडिंग (और पेर्लिन शोर) के बारे में बात कर रहे हैं, और सवाल प्रदर्शन की समस्याओं से निपटने के लिए लगता है।
थेडियन

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

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

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

1

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

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


+1 के लिए "समय से पहले अनुकूलन सभी बुराई की जड़ है" मैं इसका दोषी हूं :(
थैडियन

16
-1 एक क्वांट्री? थोडा उपर करो? जब सभी टाइलें इस तरह के 2D गेम में समान आकार की होती हैं (जो कि वे टेरारिया के लिए होती हैं), तो यह पता लगाना बेहद आसान है कि स्क्रीन पर टाइलें किस श्रेणी की हैं - यह सिर्फ ऊपरी-बाईं ओर (स्क्रीन पर) है निचले-दाहिने टाइल।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

1

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

डायनामिक एडिटिंग के बारे में ... शायद क्वाड ट्री इतना बुरा विचार नहीं है। यह मानते हुए कि टाइल्स को पत्ती में डाला जा रहा है और गैर-पत्ती के नोड्स अपने बच्चों से सिर्फ जालीदार हैं, जड़ में सभी टाइलें एक जाली में होनी चाहिए। एक टाइल को हटाने से रूट तक नोड्स अपडेट (मेष रिबेकिंग) की आवश्यकता होती है। लेकिन हर पेड़ के स्तर पर मेष का केवल 1 / 4th होता है, जो कि बहुत अधिक होता है, 4 * ट्री_हाइट मेष जुड़ता है?

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

बस मेरे विचार, कोई कोड नहीं, शायद इसकी बकवास।


0

@ शानदार सही है। समस्या ड्रॉ कोड है। आप प्रत्येक फ्रेम में 4 * 3000 + ड्रा क्वाड कमांड (24000+ ड्रा पॉलीगॉन कमांड) की एक सरणी बना रहे हैं । फिर इन कमांड को GPU के लिए प्रोसेस और पाइप किया जाता है। यह बल्कि बुरा है।

कुछ उपाय हैं।

  • एक स्थिर बनावट में टाइल्स के बड़े ब्लॉकों (उदाहरण के लिए, स्क्रीन आकार) को रेंडर करें और इसे एक कॉल में ड्रा करें।
  • GPU को हर फ्रेम में जियोमेट्री भेजे बिना टाइल खींचने के लिए shaders का प्रयोग करें (यानी GPU पर टाइल मैप को स्टोर करें)।

0

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

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

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


-2

मैं इस बारे में सोच रहा हूं कि ब्लॉक के बहुत सारे ज़िलों को कैसे हैंडल किया जाए और मेरे सिर पर आने वाली एकमात्र चीज़ फ्लाईवेट डिज़ाइन पैटर्न है। यदि आप नहीं जानते हैं, तो मैं गहराई से इसके बारे में पढ़ने का सुझाव देता हूं: स्मृति और प्रसंस्करण को बचाने के लिए बहुत मदद मिल सकती है: http://en.wikipedia.org/wiki/Flyweight_pattern


3
-1 यह उत्तर उपयोगी होने के लिए बहुत सामान्य है, और आपके द्वारा प्रदान किया गया लिंक इस विशेष समस्या को सीधे संबोधित नहीं करता है। फ्लाईवेट पैटर्न कई में से एक है, कुशलतापूर्वक बड़े डेटा सेट को प्रबंधित करने के कई तरीके; क्या आप इस बात की विस्तृत व्याख्या कर सकते हैं कि आप इस पैटर्न को टेरारिया जैसे खेल में टाइलों के भंडारण के विशिष्ट संदर्भ में कैसे लागू करेंगे?
पोस्टगूडिज्म
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.