इकाई संचार कैसे काम करता है?


115

मेरे पास दो उपयोगकर्ता मामले हैं:

  1. कैसे संदेश entity_Aभेजेगा ? take-damageentity_B
  2. एचपी की entity_Aक्वेरी कैसे होगी entity_B?

यहाँ मैंने जो अब तक का सामना किया है:

  • संदेश की कतार
    1. entity_Aएक take-damageसंदेश बनाता है और उसे entity_Bसंदेश कतार में पोस्ट करता है ।
    2. entity_Aएक query-hpसंदेश बनाता है और उसे पोस्ट करता है entity_Bentity_Bबदले में एक response-hpसंदेश बनाता है और इसे पोस्ट करता है entity_A
  • प्रकाशित करें / सदस्यता लें
    1. entity_Btake-damageसंदेशों की सदस्यता (संभवतः कुछ पूर्व-फ़िल्टरिंग के साथ इसलिए केवल प्रासंगिक संदेश दिया जाता है)। entity_Aपैदा करता है take-damageसंदेश है कि संदर्भ entity_B
    2. entity_Aupdate-hpसंदेशों के लिए सदस्यता (संभवतः फ़िल्टर्ड)। हर फ्रेम संदेशों को entity_Bप्रसारित करता है update-hp
  • सिग्नल / स्लॉट
    1. ???
    2. entity_Aएक जोड़ता है update-hpकरने के लिए स्लॉट entity_Bके update-hpसंकेत।

क्या कुछ बेहतर है? क्या मुझे इस बात की सही समझ है कि ये संचार योजनाएँ गेम इंजन की इकाई प्रणाली में कैसे बाँधेंगी?

जवाबों:


67

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

उस ने कहा, मैंने सरल संदेश पासिंग के साथ संयुक्त सिग्नल / स्लॉट मॉडल का उपयोग किया है और खुश हूं। मैंने इसे C ++ और Lua में एक काफी सफल iPhone शीर्षक के लिए उपयोग किया, जिसमें बहुत ही टाइट शेड्यूल था।

सिग्नल / स्लॉट मामले के लिए, अगर मैं चाहता हूं कि ए कुछ बी के जवाब में कुछ करने के लिए इकाई ए करे (जैसे कुछ मर जाता है तो एक दरवाजा अनलॉक करें) मेरे पास इकाई ए हो सकता है सीधे इकाई बी की मौत की घटना के लिए सदस्यता लें। या संभवतः संस्था ए प्रत्येक संस्थाओं के एक समूह को सदस्यता देगी, प्रत्येक घटना पर एक काउंटर बढ़ाएँ और एन के मरने के बाद दरवाजा अनलॉक करें। इसके अलावा, "संस्थाओं का समूह" और "उनमें से एन" आमतौर पर स्तर के डेटा में परिभाषित डिजाइनर होंगे। (एक तरफ के रूप में, यह एक ऐसा क्षेत्र है, जहां से कोरटाइन वास्तव में चमक सकते हैं, उदाहरण के लिए, WaitForMultiple ("डाइंग", enta, entB, entC); door.Unlock ();)

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

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

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

इंटरफेस, btw के संदर्भ में, मैं इस सब को लागू करने के लिए तीन वर्गों के साथ समाप्त हुआ: EventHost, EventClient, और MessageClient। EventHosts स्लॉट्स बनाते हैं, EventClients उनकी सदस्यता लेते हैं / उनसे कनेक्ट होते हैं, और MessageClients एक प्रतिनिधि को एक संदेश के साथ जोड़ते हैं। ध्यान दें कि MessageClient का प्रतिनिधि लक्ष्य आवश्यक रूप से उसी वस्तु का होना आवश्यक नहीं है जो एसोसिएशन का मालिक है। दूसरे शब्दों में, MessageClients अन्य वस्तुओं के संदेशों को अग्रेषित करने के लिए पूरी तरह से मौजूद हो सकते हैं। FWIW, होस्ट / क्लाइंट रूपक अनुचित का प्रकार है। स्रोत / सिंक बेहतर अवधारणा हो सकती है।

क्षमा करें, मैं थोमा वहाँ rambled। यह मेरा पहला उत्तर है :) मुझे आशा है कि यह समझ में आया।


जवाब के लिए धन्यवाद। महान अंतर्दृष्टि। मैसेज को पास करने का कारण लूज के कारण है। मैं नए C ++ कोड के बिना नए हथियार बनाने में सक्षम होना चाहता हूं। तो आपके विचारों ने मेरे कुछ अनसुलझे सवालों के जवाब दिए।
deft_code

के रूप में coroutines मैं भी coroutines में एक महान आस्तिक हूँ, लेकिन मैं उनके साथ C ++ में खेलने के लिए कभी नहीं। मुझे ब्लॉकिंग कॉल्स (जैसे, वेट-फॉर-डेथ) को संभालने के लिए लुआ कोड में कोरटाइन का उपयोग करने की अस्पष्ट उम्मीद थी। क्या यह प्रयास के लायक था? मुझे डर है कि मैं c ++ में coroutines के लिए अपनी तीव्र इच्छा से अंधा हो सकता हूं।
deft_code

आखिरकार, iphone गेम क्या था? क्या मैं आपके द्वारा उपयोग की जाने वाली इकाई प्रणाली के बारे में अधिक जानकारी प्राप्त कर सकता हूं?
deft_code

2
इकाई प्रणाली ज्यादातर C ++ में थी। इसलिए, उदाहरण के लिए, एक छोटा सा वर्ग था जिसने Imp के व्यवहार को संभाला। Lua स्पॉन में या संदेश के माध्यम से Imp के मापदंडों को बदल सकता है। लुआ के साथ लक्ष्य एक तंग अनुसूची में फिट होना था, और लुआ कोड को डीबग करना बहुत समय लेने वाला है। हमने Lua का उपयोग स्क्रिप्ट स्तरों पर किया (जो इकाइयाँ जहाँ जाती हैं, जब आप ट्रिगर्स को हिट करते हैं तो ऐसी घटनाएँ होती हैं)। इसलिए लुआ में, हम स्पॉनएंट ("छोटा सा भूत") जैसी चीजें कहेंगे, जहां इम्प मैन्युअल रूप से पंजीकृत फैक्ट्री एसोसिएशन है। यह हमेशा संस्थाओं के एक वैश्विक पूल में फैला रहेगा। अच्छा और सरल। हमने smart_ptr और weak_ptr का बहुत उपयोग किया ।
13

1
तो BananaRaffle: क्या आप कहेंगे कि यह आपके उत्तर का एक सटीक सारांश है: "आपके द्वारा पोस्ट किए गए सभी समाधानों में उनके उपयोग हैं, जैसा कि अन्य करते हैं। एक सही समाधान की तलाश न करें, बस उस चीज़ का उपयोग करें जिसकी आपको आवश्यकता है जहां यह समझ में आता है। । "
Ipsquiggle

76
// in entity_a's code:
entity_b->takeDamage();

आपने पूछा कि हास्य खेल कैसे करते हैं। ;)


8
एक डाउन वोट? गंभीरता से, कि यह सामान्य रूप से कैसे किया जाता है! इकाई प्रणाली महान हैं, लेकिन वे शुरुआती मील के पत्थर को हिट करने में मदद नहीं करते हैं।
तेनपुन

मैं पेशेवर रूप से फ्लैश गेम बनाता हूं, और यही मैं करता हूं। आप शत्रु.दामेज (10) को फोन करते हैं और फिर आप किसी भी जानकारी को सार्वजनिक रूप से प्राप्त करने वालों से देखते हैं।
इयान

7
यह गंभीरता से है कि व्यावसायिक खेल इंजन इसे कैसे करते हैं। वह मजाक नहीं कर रहा है। टारगेट ।NotifyTakeDamage (DamageType, DamageAmount, DamageDealer, आदि) आमतौर पर यह कैसे जाता है।
AA ग्रेपस

3
क्या कमर्शियल गेम्स में भी "नुकसान" होता है? :-P
R

15
हां, वे अन्य चीजों के अलावा, मिस्पेल क्षति करते हैं। :)
LearnCocos2D

17

एक और अधिक गंभीर जवाब:

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

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

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

अधिक उन्नत ब्लैकबोर्ड अधिक हैशटैब की तरह हो सकते हैं, मानों के लिए स्ट्रिंग मैपिंग। यह अधिक रखरखाव योग्य है, लेकिन जाहिर है कि एक रन-टाइम लागत है।

एक ब्लैकबोर्ड पारंपरिक रूप से केवल एकतरफा संचार होता है - यह डिशिंग को नुकसान से नहीं बचाएगा।


मैंने अब से पहले ब्लैकबोर्ड मॉडल के बारे में कभी नहीं सुना था।
deft_code

वे निर्भरता को कम करने के लिए भी अच्छे हैं, उसी तरह एक घटना कतार या प्रकाशित / सदस्यता मॉडल करती है।
दसपुल

2
यह भी एक "आदर्श" ई / सी / एस प्रणाली "कैसे काम करना चाहिए" की विहित "परिभाषा" है। घटक ब्लैकबोर्ड बनाते हैं; सिस्टम इस पर अभिनय कर रहे हैं। (एंटिटीज, बिल्कुल, long long intशुद्ध ईसीएस सिस्टम में, केवल s या समान हैं।)
BRPocock

6

मैंने इस मुद्दे का थोड़ा अध्ययन किया है और मैंने एक अच्छा समाधान देखा है।

मूल रूप से यह सब सिस्टम के बारे में है। यह टेनपैन द्वारा उल्लिखित ब्लैकबोर्ड विचार के समान है।

एंटिटीज़ घटकों से बने होते हैं, लेकिन वे केवल प्रॉपर्टी बैग होते हैं। संस्थाओं में कोई भी व्यवहार लागू नहीं किया जाता है।

मान लीजिए, संस्थाओं के पास स्वास्थ्य घटक और नुकसान घटक है।

फिर आपके पास कुछ MessageManager और तीन सबसिस्टम हैं: ActionSystem, DamageSystem, HealthSystem। एक बिंदु पर ActionSystem खेल की दुनिया पर अपनी गणना करता है और एक घटना उत्पन्न करता है:

HIT, source=entity_A target=entity_B power=5

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

DAMAGE, source=entity_A target=entity_B amount=7

HealthSystem ने DAMAGE संदेशों की सदस्यता ले ली है और अब जब MessageManager ने DAMAGE संदेश को HealthSystem में प्रकाशित किया है, तो HealthSystem के पास उनके स्वास्थ्य घटकों के साथ, एंटिटी_A और unit_B दोनों संस्थाओं तक पहुँच है, इसलिए फिर से HealthSystem अपनी गणना कर सकता है (और शायद इसी घटना को प्रकाशित भी कर सकता है) संदेशवाहक को)।

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

मुझे नहीं पता कि कुछ वास्तविक गेम इंजन ने इस विचार को लागू किया है या नहीं, लेकिन यह बहुत ठोस और स्वच्छ लगता है और मुझे उम्मीद है कि किसी दिन यह मेरे शौकीन स्तर के खेल इंजन के लिए खुद को लागू करेगा।


यह स्वीकृत उत्तर IMO की तुलना में बहुत बेहतर उत्तर है। घोषित, सुपाठ्य और विस्तार करने योग्य (और मजाक के जवाब की तरह एक कपल आपदा भी नहीं है entity_b->takeDamage();)
डैनी यारोस्लाव्स्की

4

वैश्विक संदेश कतार क्यों नहीं, कुछ इस तरह है:

messageQueue.push_back(shared_ptr<Event>(new DamageEvent(entityB, 10, entityA)));

साथ में:

DamageEvent(Entity* toDamage, uint amount, Entity* damageDealer);

और गेम लूप / इवेंट हैंडलिंग के अंत में:

while(!messageQueue.empty())
{
    Event e = messageQueue.front();
    messageQueue.pop_front();
    e.Execute();
}

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

DamageEvent::Execute() 
{
    toDamage->takeDamage(amount); // Or of course, you could now have entityA get points, or a recognition of damage, or anything.
}

3

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

यदि आप (या समर्थन करना चाहते हैं) मल्टीप्लेयर (बहुविकल्पी सटीक होना), कमांड कतार का उपयोग करें।

  • जब A ग्राहक B पर B को नुकसान पहुंचाता है तो क्षति की घटना को केवल पंक्तिबद्ध करता है।
  • नेटवर्क के माध्यम से कमांड कतारों को सिंक्रनाइज़ करें
  • दोनों तरफ कतारबद्ध कमांड्स को हैंडल करें।

2
यदि आप धोखेबाज़ी से बचने के बारे में गंभीर हैं, तो A ग्राहक पर बी को बिलम नहीं करता है। क्लाइंट के पास A, सर्वर पर एक "हमला B" कमांड भेजता है, जो कि वास्तव में टेनपॉन ने कहा है; सर्वर तब उस स्थिति को सभी संबंधित क्लाइंट के साथ सिंक करता है।

@ जो: हां, अगर कोई सर्वर है जो विचार करने के लिए एक वैध बिंदु है, लेकिन कभी-कभी भारी सर्वर लोड से बचने के लिए क्लाइंट (जैसे कंसोल पर) पर भरोसा करना ठीक है।
एंड्रियास

2

मैं कहूंगा: जब तक आपको स्पष्ट रूप से नुकसान से तुरंत प्रतिक्रिया की आवश्यकता नहीं है, तब तक न तो उपयोग करें।

क्षति उठाने वाली इकाई / घटक / जो भी घटनाओं को या तो एक स्थानीय घटना-कतार या एक समान स्तर पर एक प्रणाली को धकेलना चाहिए जो क्षति-घटनाओं को रखती है।

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


1

बस फोन करो। क्वेरी-एचपी द्वारा folllowed अनुरोध-एचपी न करें - यदि आप उस मॉडल का पालन करते हैं तो आप चोट की दुनिया के लिए होंगे।

आप मोनो कॉन्टुएशन पर भी एक नज़र रखना चाहते हैं। मुझे लगता है कि यह एनपीसी के लिए आदर्श होगा।


1

यदि एक ही अपडेट () चक्र में प्रत्येक ए हिट करने के लिए हमारे पास खिलाड़ी A और B है तो क्या होता है? मान लीजिए कि खिलाड़ी A के लिए अद्यतन () अपडेट A (Cycle 1 में खिलाड़ी B के लिए) (या जो भी आप इसे कहते हैं) से पहले होता है। मेरे विचार से दो परिदृश्य हैं:

  1. एक संदेश के माध्यम से तत्काल प्रसंस्करण:

    • खिलाड़ी A.Update () देखता है कि खिलाड़ी B को हिट करना चाहता है, खिलाड़ी B को क्षति को सूचित करने वाला संदेश मिलता है।
    • खिलाड़ी B.HandleMessage () खिलाड़ी B के लिए हिट पॉइंट अपडेट करता है (उसकी मृत्यु हो जाती है)
    • खिलाड़ी B.Update () देखता है कि खिलाड़ी B मर चुका है .. वह खिलाड़ी A पर हमला नहीं कर सकता

यह अनुचित है, खिलाड़ी ए और बी को प्रत्येक खिलाड़ी को मारना चाहिए, खिलाड़ी बी को ए को मारने से पहले ही मर गया क्योंकि उस इकाई / गेमबजेक्ट को अपडेट मिला () बाद में।

  1. संदेश को पंक्तिबद्ध करना

    • प्लेयर ए.उपडेट () देखता है कि खिलाड़ी बी को हिट करना चाहता है, खिलाड़ी बी को एक संदेश मिलता है जो नुकसान को सूचित करता है और इसे एक कतार में संग्रहीत करता है।
    • प्लेयर A.Update () इसकी कतार की जांच करता है, यह खाली है
    • खिलाड़ी BUpdate () चालों के लिए पहले जाँच करता है इसलिए खिलाड़ी B खिलाड़ी को नुकसान के साथ एक संदेश भेजता है
    • खिलाड़ी B.Update () कतार में संदेशों को भी संभालता है, खिलाड़ी A से क्षति को संसाधित करता है
    • नया चक्र (2): प्लेयर ए एक स्वास्थ्य औषधि पीना चाहता है इसलिए खिलाड़ी ए। यूपेटेट () को बुलाया जाता है और इस कदम को संसाधित किया जाता है
    • प्लेयर A.Update () संदेश कतार की जाँच करता है और खिलाड़ी B से होने वाली क्षति की प्रक्रिया करता है

फिर से यह अनुचित है .. खिलाड़ी ए को हिटपॉइंट को उसी मोड़ / चक्र / टिक में ले जाना चाहिए!


4
आप वास्तव में प्रश्न का उत्तर नहीं दे रहे हैं, लेकिन मुझे लगता है कि आपका उत्तर स्वयं एक उत्कृष्ट प्रश्न बना देगा। क्यों नहीं आगे बढ़ें और पूछें कि इस तरह के "अनुचित" प्राथमिकता को कैसे हल किया जाए?
बंमज़ैक

मुझे संदेह है कि अधिकांश खेल इस अनुचितता की परवाह करते हैं क्योंकि वे इतनी बार अद्यतन करते हैं कि यह शायद ही कभी एक मुद्दा है। अद्यतन करते समय इकाई सूची के माध्यम से आगे और पीछे पुनरावृति के बीच वैकल्पिक एक सरल समाधान है।
काइलोटन

मैं 2 कॉल का उपयोग करता हूं इसलिए मैं सभी संस्थाओं को अपडेट () कॉल करता हूं, फिर लूप के बाद मैं फिर से पुनरावृति करता हूं और कुछ कॉल करता हूं pEntity->Flush( pMessages );। जब Unit_A एक नई घटना उत्पन्न करता है, तो उस फ्रेम में Unit_B द्वारा इसे नहीं पढ़ा जाता है (इसमें पोशन लेने का भी मौका होता है) तब दोनों को नुकसान होता है और इसके बाद वे पोशन हीलिंग के संदेश को संसाधित करते हैं जो कतार में अंतिम होगा । प्लेयर बी अभी भी वैसे भी मर जाता है क्योंकि पोशन संदेश कतार में अंतिम है: P लेकिन यह अन्य प्रकार के संदेशों के लिए उपयोगी हो सकता है जैसे कि मृत संस्थाओं को संकेत देना।
पाब्लो एरियल

मुझे लगता है कि फ्रेम स्तर पर, अधिकांश खेल कार्यान्वयन केवल अनुचित हैं। जैसे कि किलोटन ने कहा।
v.oddou

इस समस्या को हल करना आसान है। बस संदेश संचालकों में या जो भी हो, एक दूसरे को नुकसान को लागू करें। आपको निश्चित रूप से खिलाड़ी को संदेश हैंडलर के अंदर मृत नहीं करना चाहिए। "अपडेट ()" में आप बस "यदि (hp <= 0) मर जाते हैं ();" (उदाहरण के लिए "अपडेट ()" की शुरुआत में)। इस तरह दोनों एक ही समय में एक दूसरे को मार सकते हैं। इसके अलावा: अक्सर आप खिलाड़ी को सीधे नुकसान नहीं पहुंचाते हैं, लेकिन बुलेट जैसी किसी मध्यवर्ती वस्तु के माध्यम से।
तारा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.