खिलाड़ी और दुनिया के बीच परिपत्र निर्भरता से कैसे बचें?


60

मैं एक 2D गेम पर काम कर रहा हूँ जहाँ आप ऊपर, नीचे, बाएँ और दाएँ घूम सकते हैं। मेरे पास अनिवार्य रूप से दो गेम लॉजिक ऑब्जेक्ट हैं:

  • खिलाड़ी: दुनिया के सापेक्ष एक स्थिति है
  • विश्व: मानचित्र और खिलाड़ी को खींचता है

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

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

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

मेरा सबसे अच्छा विकल्प क्या है? या एक परिपत्र निर्भरता से बचने लायक नहीं है?


4
आपको क्या लगता है कि एक परिपत्र निर्भरता एक बुरी बात है? stackoverflow.com/questions/1897537/…
फ्यूहरमैनेटर

@Fuhrmanator मुझे नहीं लगता कि वे आम तौर पर एक बुरी चीज हैं, लेकिन मुझे एक को पेश करने के लिए चीजों को अपने कोड में कुछ अधिक जटिल बनाना होगा।
17

मैं हमारी छोटी चर्चा के बारे में एक पोस्ट करता हूं, हालांकि कुछ भी नया नहीं है: yannbane.com/2012/11/… ...
jcora

जवाबों:


61

दुनिया को अपनी ओर नहीं खींचना चाहिए; रेंडरर को दुनिया को आकर्षित करना चाहिए। खिलाड़ी को खुद को आकर्षित नहीं करना चाहिए; रेंडरर को खिलाड़ी को दुनिया के सापेक्ष आकर्षित करना चाहिए।

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

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


25
@ स्नेक 5 - "कैन" और "चाहिए" के बीच अंतर है। कुछ भी कुछ भी आकर्षित कर सकता है - लेकिन जब आपको कोड बदलने की ज़रूरत होती है जो ड्राइंग से संबंधित है, तो "रेंडरर" क्लास में जाना बहुत आसान है बजाय इसके कि "कुछ भी" ड्राइंग के लिए खोज की जाए। "कम्पार्टमेंटलाइज़ेशन पर जुनूनी" "सामंजस्य" के लिए एक और शब्द है।
नैट

16
@ Mr.Beast, नहीं, वह नहीं है। वह अच्छे डिजाइन की वकालत कर रहा है। एक वर्ग की एक गड़गड़ाहट में सब कुछ cramming कोई मतलब नहीं है।
जेकोरा

23
वाह, मुझे नहीं लगा कि यह इस तरह की प्रतिक्रिया को चिंगारी देगा :) मेरे पास जवाब में जोड़ने के लिए कुछ भी नहीं है, लेकिन मैं समझा सकता हूं कि मैंने इसे क्यों दिया - क्योंकि मुझे लगता है कि यह सरल है। 'उचित' या 'सही' नहीं। मैं नहीं चाहता था कि वह इस तरह से आवाज़ करे। यह मेरे लिए सरल है क्योंकि अगर मैं खुद को बहुत सारी जिम्मेदारियों के साथ कक्षाओं से निपटता हुआ पाता हूं, तो मौजूदा कोड को पठनीय होने के लिए मजबूर करने की तुलना में एक विभाजन तेजी से होता है। मुझे लगता है कि मैं समझ सकता हूँ, और एक @futlib जैसी समस्याओं की प्रतिक्रिया में रिफ्लेक्टर में कोड पसंद है।
लियोन

12
@ स्नेक 5 यह कहना कि अधिक क्लासेस जोड़ना प्रोग्रामर के लिए ओवरहेड है, मेरे अनुभव में अक्सर पूरी तरह से गलत है। मेरी राय में सूचनात्मक नाम और अच्छी तरह से परिभाषित जिम्मेदारियों के साथ 10x100 लाइन कक्षाएं पढ़ने के लिए आसान है और प्रोग्रामर के लिए एक सिंगल लाइन लाइन क्लास की तुलना में कम ओवरहेड है
मार्टिन

7
एक चीज़ के बारे में एक नोट के रूप में, जो Rendererकुछ प्रकार का है, वह आवश्यक है, लेकिन इसका मतलब यह नहीं है कि प्रत्येक चीज़ को कैसे प्रदान किया जाता है Renderer, इसके लिए तर्क को नियंत्रित किया जाता है , प्रत्येक चीज़ जिसे खींचना आवश्यक है, उसे संभवतः एक सामान्य इंटरफ़ेस से विरासत में प्राप्त करना चाहिए जैसे कि IDrawableया IRenderable(या जो भी भाषा आप उपयोग कर रहे हैं, उसके समतुल्य इंटरफ़ेस)। दुनिया हो सकती है Renderer, मुझे लगता है, लेकिन ऐसा लगता है कि यह अपनी जिम्मेदारी से बचना होगा, खासकर अगर यह पहले से IRenderableही एक था।
zzzzBov

35

यहाँ बताया गया है कि एक विशिष्ट रेंडरिंग इंजन इन चीजों को कैसे संभालता है:

जहाँ वस्तु किसी अंतरिक्ष में होती है और वस्तु कैसे खींची जाती है, उसके बीच एक मूलभूत अंतर होता है।

  1. किसी वस्तु को खींचना

    आपके पास आमतौर पर एक रेंडरर वर्ग होता है जो ऐसा करता है। यह बस एक वस्तु (मॉडल) लेता है और स्क्रीन पर आ जाता है। इसमें drawSprite (Sprite), drawLine (..), drawModel (मॉडल) जैसे तरीके हो सकते हैं, जो भी आपको जरूरत महसूस हो। यह एक रेंडरर है इसलिए इसे इन सभी चीजों को करना चाहिए। यह आपके द्वारा नीचे दिए गए किसी भी एपीआई का उपयोग करता है इसलिए आपके पास एक रेंडरर हो सकता है जो ओपनजीएल का उपयोग करता है और एक वह जो डायरेक्टएक्स का उपयोग करता है। यदि आप अपने गेम को किसी अन्य प्लेटफॉर्म पर पोर्ट करना चाहते हैं, तो आप बस एक नया रेंडर लिखते हैं और उस एक का उपयोग करते हैं। इट्स दैट ईजी।

  2. किसी वस्तु को हिलाना

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

  3. वस्तुओं का प्रबंध करना

    कैसे SceneNodes प्रबंधित कर रहे हैं? एक दृश्य प्रबंधक के माध्यम से । यह वर्ग आपके दृश्य में प्रत्येक दृश्य के ट्रैक बनाता है और रखता है। आप इसे एक विशिष्ट सीन (आमतौर पर "प्लेयर" या "टेबल" जैसे स्ट्रिंग नाम से पहचाना जाता है) या सभी नोड्स की सूची के लिए पूछ सकते हैं।

  4. दुनिया को आकर्षित करना

    यह अब तक बहुत स्पष्ट होना चाहिए। बस दृश्य में हर दृश्य के माध्यम से चलना और रेंडरर को सही जगह पर खींचना है। रेंडरर को रेंडर करने से पहले आप रेंडरर को स्टोर करके स्टोर कर सकते हैं।

  5. टक्कर की पहचान हुई है

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

तो, खिलाड़ी क्या है, और दुनिया क्या है?

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

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


+1 - मैंने खुद को अपने गेम सिस्टम को कुछ इस तरह से बनाते हुए पाया है, और इसे काफी लचीला पाया है।
साइपर

+1, बढ़िया जवाब। मेरे खुद की तुलना में अधिक ठोस और बिंदु तक।
जकौरा

+1, मैंने इस उत्तर से बहुत कुछ सीखा और यह एक प्रेरक अंत भी था। धन्यवाद @rootlocus
joslinm

16

आप उससे बचना क्यों चाहेंगे? यदि आप पुन: प्रयोज्य वर्ग बनाना चाहते हैं तो परिपत्र निर्भरता से बचना चाहिए। लेकिन प्लेयर कोई भी ऐसा वर्ग नहीं है जिसे पुन: उपयोग करने की आवश्यकता हो। क्या आप कभी भी खिलाड़ी का उपयोग दुनिया के बिना करना चाहेंगे? शायद ऩही।

याद रखें कि कक्षाएं कार्यक्षमता के संग्रह से ज्यादा कुछ नहीं हैं। सवाल सिर्फ यह है कि कार्यक्षमता को कैसे विभाजित किया जाए। आपको जो भी करना है वह करें। यदि आपको एक परिपत्र पतन की आवश्यकता है, तो ऐसा हो। (एक ही तरह से किसी भी OOP सुविधाओं के लिए चला जाता है। चीजों को एक तरह से कोड करें कि यह एक उद्देश्य प्रदान करता है, बस पैराडम्स का आँख बंद करके पालन न करें।)

संपादित करें
ठीक है, प्रश्न का उत्तर देने के लिए: आप कॉलबैक का उपयोग करके खिलाड़ी को टक्कर की जांच के लिए दुनिया को जानने की जरूरत से बच सकते हैं:

World::checkForCollisions()
{
  [...]
  foreach(entityA in entityList)
    foreach(entityB in entityList)
      if([... entityA and entityB have collided ...])
         entityA.onCollision(entityB);
}

Player::onCollision(other)
{
  [... react on the collision ...]
}

अगर आप संस्थाओं के वेग को उजागर करते हैं, तो आपके द्वारा प्रश्न में वर्णित भौतिकी की दुनिया को संभाला जा सकता है:

World::calculatePhysics()
{ 
  foreach(entityA in entityList)
    foreach(entityB in entityList)
    {
      [... move entityA according to its velocity as far as possible ...]
      if([... entityA has collided with the world ...])
         entityA.onWorldCollision();
      [... calculate the movement of entityB in order to know if A has collided with B ...]
      if([... entityA and entityB have collided ...])
         entityA.onCollision(entityB);
    }
}

हालाँकि, ध्यान दें कि शायद आपको दुनिया पर जल्दी या बाद में एक निर्भरता की आवश्यकता होगी, जब भी आपको दुनिया की कार्यक्षमता की आवश्यकता होती है: आप जानना चाहते हैं कि निकटतम दुश्मन कहाँ है? आप यह जानना चाहते हैं कि अगली कगार कितनी दूर है? निर्भरता यह है


4
+1 परिपत्र निर्भरता वास्तव में यहाँ कोई समस्या नहीं है। इस स्तर पर इस बारे में चिंता करने का कोई कारण नहीं है। यदि खेल बढ़ता है और कोड परिपक्व होता है, तो संभवतः उन खिलाड़ियों और विश्व वर्गों को उप-वर्गों में फिर से जोड़ना एक अच्छा विचार होगा, एक उचित घटक-आधारित प्रणाली, इनपुट हैंडलिंग के लिए कक्षाएं, शायद एक रेंडर, आदि। एक शुरुआत, कोई समस्या नहीं।
लॉरेंट कौविदो

4
-1, यह निश्चित रूप से एकमात्र कारण नहीं है कि परिपत्र निर्भरता का परिचय न हो। उनका परिचय न देकर, आप अपने सिस्टम को विस्तार और बदलने में आसान बनाते हैं।
जेकोरा

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

3
नहीं, आप गोलपोस्ट ले जा रहे हैं। जरूर कुछ तो पुकारना होगा render(World)। बहस इस बात के आसपास है कि क्या सभी कोड को एक वर्ग के अंदर रखा जाना चाहिए, या क्या कोड को तार्किक और कार्यात्मक इकाइयों में विभाजित किया जाना चाहिए, जो तब बनाए रखने, विस्तार करने और प्रबंधन करने में आसान होते हैं। BTW, सौभाग्य उन घटक प्रबंधकों, भौतिकी इंजन और इनपुट प्रबंधकों का पुन: उपयोग कर रहा है, जो सभी चतुराई से उदासीन और पूरी तरह से युग्मित हैं।
jcora

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

13

आपका वर्तमान डिजाइन SOLID डिजाइन के पहले सिद्धांत के खिलाफ जाता है ।

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

समेटने के लिए, आपकी Worldवस्तु गेम स्टेट को अपडेट और होल्ड करने और सब कुछ ड्राइंग के लिए दोनों के लिए जिम्मेदार है।

क्या होगा अगर आपका रेंडरिंग कोड बदल जाए / बदलना पड़े? आपको उन दोनों वर्गों को क्यों अपडेट करना चाहिए जो वास्तव में प्रतिपादन के साथ कुछ नहीं करते हैं? जैसा कि लिओसन पहले ही कह चुके हैं, आपके पास होना चाहिए Renderer


अब, आपके वास्तविक प्रश्न का उत्तर देने के लिए ...

ऐसा करने के कई तरीके हैं, और यह केवल डिकोडिंग का एक तरीका है:

  1. दुनिया को पता नहीं है कि खिलाड़ी क्या है।
    • इसमें Objects की एक सूची है , जिसमें खिलाड़ी स्थित है, लेकिन यह खिलाड़ी वर्ग पर निर्भर नहीं करता है (इसे प्राप्त करने के लिए विरासत का उपयोग करें)।
  2. खिलाड़ी कुछ द्वारा अद्यतन किया जाता है InputManager
  3. दुनिया आंदोलन और टकराव का पता लगाने, उचित भौतिक परिवर्तनों को लागू करने और वस्तुओं को अपडेट भेजने का काम संभालती है।
    • उदाहरण के लिए, यदि ऑब्जेक्ट A और ऑब्जेक्ट B टकराते हैं, तो दुनिया उन्हें सूचित करेगी और फिर वे स्वयं इसे संभाल सकते हैं।
    • दुनिया अभी भी भौतिकी को संभालती है (यदि आपका डिजाइन ऐसा है)।
    • फिर, दोनों वस्तुएं देख सकती हैं कि टकराव उनके हित में है या नहीं। उदाहरण के लिए, यदि ऑब्जेक्ट A खिलाड़ी था, और ऑब्जेक्ट B एक स्पाइक था, तो खिलाड़ी खुद को नुकसान पहुंचा सकता है।
    • यह अन्य तरीकों से हल किया जा सकता है, हालांकि।
  4. Rendererसभी वस्तुओं को खींचता है।

आप कहते हैं कि दुनिया को पता नहीं है कि खिलाड़ी क्या है, लेकिन यह टकराव का पता लगाता है, जिसे खिलाड़ी की संपत्तियों को जानने की आवश्यकता हो सकती है, यदि यह टकराव की वस्तुओं में से एक है।
मार्कस वॉन ब्रॉडी

वंशानुक्रम, दुनिया को कुछ प्रकार की वस्तुओं के बारे में पता होना चाहिए, जिन्हें सामान्य तरीके से वर्णित किया जा सकता है। समस्या यह नहीं है कि दुनिया में सिर्फ खिलाड़ी का संदर्भ है, लेकिन यह उस पर एक वर्ग के रूप में निर्भर हो सकता है (जैसे healthकि केवल इस तरह के क्षेत्रों का उपयोग करें Player)।
जकोरा

आह, आपका मतलब है कि दुनिया में खिलाड़ी के लिए कोई संदर्भ नहीं है, इसमें सिर्फ ऑब्जेक्ट्स की एक सरणी है जो ICollidable इंटरफ़ेस को लागू करता है, साथ में यदि आवश्यक हो तो खिलाड़ी के साथ।
मार्कस वॉन ब्रोडैडी

2
+1 अच्छा जवाब। लेकिन: "कृपया सभी लोगों को अनदेखा करें जो कहते हैं कि अच्छा सॉफ्टवेयर डिज़ाइन महत्वपूर्ण नहीं है"। सामान्य। ऐसा किसी ने नहीं कहा।
लॉरेंट कौविदो

2
संपादित! यह वैसे भी अनावश्यक लग रहा था ...
jcora

1

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

परिपत्र संदर्भ के संदर्भ में आप जो बचना चाहते हैं, वह एक-दूसरे के संदर्भ में बहुत अधिक नहीं है, बल्कि कोड में स्पष्ट रूप से एक-दूसरे का जिक्र है।


1

जब भी दो अलग-अलग प्रकार की वस्तुएं एक-दूसरे से पूछ सकती हैं। वे एक-दूसरे पर निर्भर होंगे क्योंकि उन्हें अपने तरीकों को कॉल करने के लिए दूसरे के लिए एक संदर्भ रखने की आवश्यकता होती है।

आप विश्व को खिलाड़ी से पूछकर परिपत्र निर्भरता से बच सकते हैं, लेकिन खिलाड़ी विश्व से पूछ नहीं सकता है, या इसके विपरीत नहीं पूछ सकता है। इस तरह विश्व में खिलाड़ियों के संदर्भ हैं लेकिन खिलाड़ियों को विश्व के संदर्भ की आवश्यकता नहीं है। या ठीक इसके विपरीत। लेकिन इससे समस्या का समाधान नहीं होगा, क्योंकि दुनिया को खिलाड़ियों से पूछना होगा कि क्या उन्हें कुछ पूछना है, और अगली कॉल में उन्हें बताना होगा ...

तो आप वास्तव में इस "समस्या" के आसपास काम नहीं कर सकते हैं और मुझे लगता है कि इसके बारे में चिंता करने की कोई आवश्यकता नहीं है। जब तक आप कर सकते हैं तब तक डिजाइन को सरल रखें।


0

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

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

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

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

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


0

जैसा कि दूसरों ने कहा है, मुझे लगता है कि आपका Worldएक काम बहुत अधिक हो रहा है: यह दोनों को खेल Map(जिसमें एक अलग इकाई होना चाहिए) और एक Rendererही समय में होने की कोशिश कर रहा है।

इसलिए एक नया ऑब्जेक्ट बनाएं (जिसे GameMap, संभवतः कहा जाता है ), और इसमें मैप स्तर डेटा संग्रहीत करें। इसमें ऐसे कार्य लिखें जो वर्तमान मानचित्र के साथ सहभागिता करते हैं।

फिर आपको एक वस्तु की भी आवश्यकता है Renderer। आप इस वस्तु को वह चीज बना सकते हैं जिसमेंRenderer दोनों ( और साथ ही ) शामिल हैं, और उन्हें भी आकर्षित करता है। GameMapPlayerEnemies


-6

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

परिपत्र संदर्भ के कारण होने वाली समस्याओं को प्रभावी ढंग से रोकने के लिए खिलाड़ी वस्तु को नष्ट करने से पहले / संदर्भ को नष्ट करना भी संभव है।


1
मैं तुम्हारे साथ हूँ। OOP बहुत ओवररेटेड है। बुनियादी नियंत्रण प्रवाह सामग्री सीखने के बाद ट्यूटोरियल और शिक्षा ओओ के लिए तेजी से कूदते हैं। OO प्रोग्राम आम तौर पर प्रक्रियात्मक कोड की तुलना में धीमे होते हैं, क्योंकि आपकी वस्तुओं के बीच नौकरशाही होती है, आपके पास बहुत सारे पॉइंटर एक्सेस होते हैं, जो कैश मिस के लोड को कम करता है। आपका खेल काम करता है लेकिन बहुत धीमा। कैश ग्लोबल से बचने के लिए सब कुछ के लिए सादे वैश्विक सरणियों और हाथ से अनुकूलित, ठीक ट्यून किए गए कार्यों का उपयोग करके वास्तविक, बहुत तेज और समृद्ध गेम। जिसके परिणामस्वरूप प्रदर्शन में दस गुना वृद्धि हो सकती है।
कैलेमरियस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.