बारी-आधारित गेम में इकाई-घटक गेमस्टेट की प्रगति कैसे करें?


9

अब तक मैंने जिस इकाई घटक प्रणाली का उपयोग किया है, वह ज्यादातर जावा की आर्टेमिस की तरह काम करती है:

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

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

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

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

ईवेंट अन्य ईवेंट को भी ट्रिगर कर सकते हैं। कवच का उपयोग करके तलवार की क्षति को कम करने से तलवार को चकनाचूर किया जा सकता है (क्षति कम होने से पहले यह पूरा होना चाहिए), जो बदले में इसके जवाब में अतिरिक्त घटनाओं का कारण बन सकता है, अनिवार्य रूप से घटनाओं का पुनरावर्ती मूल्यांकन।

सभी सब में, यह कुछ समस्याओं का कारण बनता है:

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

उपर्युक्त दो बिंदु यह मानते हैं कि सिस्टम समान संस्थाओं पर काम करते हैं, जो अपने घटकों में झंडे का उपयोग करके बदलते हुए राज्य को समाप्त करते हैं।

इसे हल करने का एक और तरीका यह होगा कि आप एक ही सिस्टम को गेम्स स्टेट को आगे बढ़ाने के लिए कंपोनेंट्स को जोड़ना / हटाना (या पूरी तरह से नई इकाइयाँ बनाना) कर सकते हैं। इसका मतलब यह है कि जब भी किसी सिस्टम में वास्तव में एक मिलान इकाई होती है, तो वह जानता है कि इसे संसाधित करने की अनुमति है।

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

क्या यह मेरे साथ रहना है? मेरे द्वारा देखे गए हर एक ईसीएस उदाहरण का वास्तविक समय हो गया है, और यह देखना आसान है कि यह एक-प्रतिगमन-प्रति-गेम-लूप ऐसे मामलों में कैसे काम करता है। और मुझे अभी भी इसे प्रस्तुत करने की आवश्यकता है, यह वास्तव में उन प्रणालियों के लिए वास्तव में अयोग्य है जो हर बार कुछ होने पर खुद के अधिकांश पहलुओं को रोकते हैं।

क्या गेम स्टेट को आगे बढ़ाने के लिए कुछ डिज़ाइन पैटर्न है जो इसके लिए उपयुक्त है, या मुझे बस सभी लॉजिक को लूप से बाहर ले जाना चाहिए और इसके बजाय इसे केवल तब ही ट्रिगर करना चाहिए?


आप वास्तव में होने वाली घटना के लिए चुनाव नहीं करना चाहते हैं। एक घटना केवल तब होती है जब यह होता है। क्या आर्टेमिस सिस्टम को एक दूसरे के साथ संवाद करने की अनुमति नहीं देता है?
सिदार

यह करता है, लेकिन केवल तरीकों का उपयोग करके उन्हें युग्मन द्वारा।
एरिस 130

जवाबों:


3

यहां मेरी सलाह एक आरपीजी प्रोजेक्ट पर पिछले अनुभव से आ रही है जहां हमने एक घटक प्रणाली का उपयोग किया था। मैं कहूंगा कि मुझे उस गेमसाइड कोड में काम करने से नफरत थी क्योंकि यह स्पेगेटी कोड था। इसलिए मैं यहाँ एक उत्तर की पेशकश नहीं कर रहा हूँ, बस एक परिप्रेक्ष्य:

एक खिलाड़ी को तलवार की क्षति से निपटने के लिए आपके द्वारा वर्णित तर्क ... ऐसा लगता है कि एक प्रणाली को उस सभी का प्रभारी होना चाहिए।

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

के रूप में बर्बाद प्रसंस्करण चक्र के लिए ... HandleWeaponHit () केवल ट्रिगर किया जाना चाहिए जब जरूरत (तलवार का पता लगाने पर)।

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


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

1
आपके पास एक तंग enmeshed मुकाबला अनुक्रम है इसलिए हां, प्रभाव ट्रिगर करने के लिए जिम्मेदार है। हर चीज को छोटे सिस्टम में तोड़ना नहीं पड़ता है, इसे एक सिस्टम को संभालने दें क्योंकि यह वास्तव में आपका "कॉम्बैट सिस्टम" है और यह हैंडल करता है ... कॉम्बैट ...
पैट्रिक ह्यूजेस

3

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

मुझे यकीन नहीं है कि अगर यह ईसीएस अवधारणाओं का उल्लंघन करता है, लेकिन क्या अगर:

  • सिस्टम ऑब्जेक्ट्स (वास्तव में शुद्ध डेटा, लेकिन मुझे नहीं लगता कि एक घटक है) को जारी करने / सदस्यता लेने के लिए एक EventBus जोड़ें
  • प्रत्येक मध्यवर्ती स्थिति के लिए घटक बनाएँ

उदाहरण:

  • UserInputSystem [DamageDealerEntity, DamageReceiverEntity, Skill / हथियार इस्तेमाल की गई जानकारी] के साथ एक हमले की घटना को आग लगाता है ]
  • CombatSystem इसे सब्सक्राइब किया जाता है और DamageReceiver के लिए चोरी के मौके की गणना करता है। यदि चोरी विफल हो जाती है तो यह उसी पैरामीटर के साथ डैमेज इवेंट को ट्रिगर करता है
  • डैमेजसिस्टम को इस तरह की घटना के लिए सब्सक्राइब किया जाता है और इस तरह ट्रिगर किया जाता है
  • डैमेजसिस्टम स्ट्रेंथ, बेसवेपॉन डैमेज, इसके प्रकार आदि का उपयोग करता है और इसे एक नए इनकमिंगडैमेजकंपोनेंट को [डैमेजडेलर एंइटी, फाइनलऑउटगोइंगडैमेज, डैमेज टाइप] के साथ लिखता है और इसे नुकसान रिसीवर एंटिटी / एंटिटीज से जोड़ देता है।
  • डैमेजसिस्टम एक आउटगोइंगडैमेज को निकाल देता है
  • इसके द्वारा आर्मोरसिस्टम को ट्रिगर किया जाता है, एक रिसीवर एंटिटी को चुनता है या इनकमिंगडैमेज पहलू को इनसाइट्स में इनकमिंगडैमेजकंपोनेंट (पिछले एक शायद फैल के साथ कई हमलों के लिए बेहतर हो सकता है) उठाता है और कवच और नुकसान की गणना करता है। तलवार बिखरने के लिए वैकल्पिक रूप से घटनाओं को ट्रिगर करता है
  • ArmorSystems प्रत्येक इकाई में InDDageageComponent को निकालता है और इसे अंतिम गणना की गई संख्याओं के साथ DamageReceivedComponent से बदल देता है जो HP को संक्रमित करेगा और घावों से गति में कमी करेगा।
  • ArmorSystems एक आगामी आने वाले कार्यक्रम को भेजता है
  • स्पीड सिस्टम को सब्सक्राइब किया जाता है और स्पीड को रिकॉल करता है
  • HealthSystem को सब्सक्राइब किया जाता है और वास्तविक HP को घटाया जाता है
  • आदि
  • किसी तरह साफ किया

पेशेवरों:

  • सिस्टम जटिल श्रृंखला की घटनाओं के लिए मध्यवर्ती डेटा प्रदान करने वाले एक दूसरे को ट्रिगर करते हैं
  • EventBus द्वारा Decoupling

विपक्ष:

  • मुझे लगता है कि मैं चीजों को पारित करने के दो तरीकों को मिलाता हूं: घटना के पैरामीटर्स में और अस्थायी घटकों में। यह एक कमजोर जगह हो सकती है। सिद्धांत रूप में, चीजों को सजातीय रखने के लिए मैं बिना किसी डेटा के बस एनम घटनाओं को आग लगा सकता हूं ताकि सिस्टम को पहलू द्वारा निहित घटकों में निहित पैरामीटर मिल जाए ... निश्चित नहीं है कि क्या यह ठीक है, हालांकि
  • सुनिश्चित नहीं है कि कैसे पता चले कि सभी संभावित इच्छुक SystemHave ने IncomingDamageCalculated संसाधित किया ताकि इसे साफ किया जा सके और अगली बारी हो। शायद CombatSystem में कुछ प्रकार के चेक वापस ...

2

समाधान पोस्ट करने के बाद मैं आखिरकार यकोवलेव के समान हो गया।

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

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

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

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

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

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

एक मुद्दा जो सामने आया था कि यह सुनिश्चित किया जाता है कि प्रतिक्रिया-घटनाओं को उनके भेजे गए क्रम में संसाधित किया जाए, यह देखते हुए कि कुछ प्रतिक्रियाएं अतिरिक्त प्रतिक्रियाएं पैदा कर सकती हैं। उदाहरण:

खिलाड़ी चाल चलता है, जिससे खिलाड़ी इकाई को भेजा जा रहा है और आंदोलन प्रणाली द्वारा उठाए जाने वाले आंदोलन की घटना होती है।

कतार में: आंदोलन

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

कतार में: टर्नओवर

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

कतार में: नुकसान, टर्नओवर

अब तक सब ठीक है, क्षति की घटना पर कार्रवाई की जाएगी, और फिर बारी समाप्त हो जाएगी। हालांकि, क्या होगा अगर अतिरिक्त घटनाओं को नुकसान की प्रतिक्रिया के रूप में भेजा जाता है? अब घटना कतार की तरह दिखेगा:

कतार में: नुकसान, टर्नओवर, ResponseToDamage

दूसरे शब्दों में, क्षति समाप्त होने से पहले किसी भी प्रतिक्रिया को संसाधित करने के लिए बारी समाप्त हो जाएगी।

इसे हल करने के लिए मैंने ईवेंट भेजने के दो तरीकों का उपयोग करके समाप्त किया: भेजें (ईवेंट, इकाई) और प्रतिसाद (ईवेंट, EventToRespondTo, एंटिटी)।

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

उसके ऊपर, एक चर-लंबाई सरणी का उपयोग कई इवेंट कतारों को करने के लिए किया जाता है। जब भी किसी घटना को प्रबंधक द्वारा प्राप्त किया जाता है, तो उस घटना को सरणी में एक सूचकांक में एक कतार में जोड़ा जाता है जो प्रतिक्रिया श्रृंखला में घटनाओं की मात्रा से मेल खाती है। इस प्रकार प्रारंभिक आंदोलन घटना को कतार में जोड़ा जाता है [0], और क्षति के साथ-साथ टर्नओवर घटनाओं को एक अलग कतार में जोड़ा जाता है [1] क्योंकि दोनों को आंदोलन की प्रतिक्रियाओं के रूप में भेजा गया था।

जब क्षति घटना की प्रतिक्रियाएं भेजी जाती हैं, तो उन घटनाओं में क्षति की घटना दोनों ही शामिल होगी, साथ ही आंदोलन, उन्हें सूचकांक [2] पर एक कतार में डाल देगा। जब तक अनुक्रमणिका [n] की अपनी कतार में घटनाएँ होती हैं, उन घटनाओं को [n-1] पर जाने से पहले संसाधित किया जाएगा। यह एक प्रसंस्करण आदेश देता है:

आंदोलन -> नुकसान [१] -> प्रतिक्रिया प्रतिक्रिया [२] -> [२] खाली है -> टर्नओवर [१] -> [१] खाली है -> [०] खाली है

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