मैं विभिन्न प्रकार के आक्रमणों को कैसे डिज़ाइन कर सकता हूं जो संयुक्त हो सकते हैं?


17

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

चम्मच बेंडर इसहाक को घर के आँसू शूट करने की क्षमता देता है।

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

इसहाक को ट्रिपल शॉट देता है

इस तरह की चीजों को डिजाइन करने के लिए एक अच्छा आर्किटेक्चर क्या है? यहाँ एक क्रूर बल समाधान है:

if not spoon bender and not the inner eye then ...
if spoon bender and not the inner eye then ...
if not spoon bender and the inner eye then ...
if spoon bender and the inner eye then ...

लेकिन यह बहुत तेजी से हाथ से निकल जाएगा। इस तरह की प्रणाली को डिजाइन करने का एक बेहतर तरीका क्या है?


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

2
मैं यह बताना चाहूंगा कि किर्बी 64 ने सभी संभावित संयोजनों के लिए जानवर-बल के दृष्टिकोण और कठिन-प्रोग्राम के विभिन्न प्रभावों को लिया है, इसलिए यह उचित है।
केविन

जवाबों:


16

आपको पूरी तरह से हाथ-कोड संयोजन की आवश्यकता नहीं है। आप इसके बजाय उन गुणों पर ध्यान केंद्रित कर सकते हैं जो प्रत्येक आइटम आपको देता है। उदाहरण के लिए, आइटम ए सेट Projectile=Fireball,Targetting=Homingआइटम बी सेट FireMode=ArcShot,Count=3ArcShotतर्क भेजने के लिए जिम्मेदार है Countकी संख्याProjectile एक चाप में आइटम नहीं है।

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

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

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


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

1
@tieTYT: मैंने नामों को सामान्यीकृत किया और प्रोजेक्टाइल प्रकारों और फायरिंग मोड्स के अलावा लक्ष्यीकरण मोड्स को शामिल करने के लिए उदाहरण का विस्तार किया। कभी भी BoI को कुछ मिनटों से अधिक के लिए नहीं खेला जाता है, इसलिए मेरे पास अन्य के रूप में आंतरिक रूप में नाम नहीं हैं। :)
सीन मिडिलिचच

यह मुझे लगता है कि मुश्किल हिस्सा गुणों की श्रेणियों की पहचान कर रहा है। उदाहरण: लक्ष्यीकरण एक है, फायरमॉड एक और है, काउंट 3 हो सकता है ... या यह नहीं हो सकता है। शायद 3 प्रोजेक्टाइल एक आग का गोला हो सकते हैं और 5 ग्रेनेड हो सकते हैं भले ही यह एक हथियार हो।
डैनियल कपलान

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

यहाँ इस बारे में एक शानदार वीडियो है कि आप प्रक्रियात्मक प्रोग्रामिंग youtu.be/QM1iUe6IofM के बारे में गलत क्यों हैं , साथ ही डेटा चालित तरीका जिसे आप किसी भी तरह से मानचित्रों का वर्णन करते हैं / यदि आप व्यक्तिगत डेटा सेटों में ब्लॉक करते हैं, तो अनिवार्य रूप से यह कम करने के लिए कि आपको कितने विशेष मामलों में कुछ भी नहीं करना है। कार्यक्रम, जैसा कि आपको उन सभी को प्रोग्राम करना है ...
RenaissanceProgrammer

8

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

क्रूड c ++ उदाहरण:

class AttackBehaviour
{
    /* other code */
    virtual void Attack(double angle);
};

class TearAttack: public AttackBehaviour
{
    /* other code */
    void Attack(double angle);
};

class TripleAttack: public AttackBehaviour
{
    /* other code */
    AttackBehaviour* baseAttackBehaviour;
    void Attack(double angle);
};

void TripleAttack::Attack(angle)
{
    baseAttackBehaviour->Attack(angle-30);
    baseAttackBehaviour->Attack(angle);
    baseAttackBehaviour->Attack(angle+30);
}

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


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

इसका अधिक कठोर क्योंकि संशोधक हमेशा Attackउस वस्तु की विधि को कॉल करेगा जो इसे एकत्र करता है। TripleAttackवर्ग के बारे में पता नहीं करना चाहिए TearAttackवर्ग। अगर यह सच होता तो यह else-ifब्लॉक के रूप में सिर्फ कई सिरदर्द पैदा करता । इसका मतलब यह है कि किसी भी आंसू एनिमेशन को TearAttackBehaviourऑब्जेक्ट के अंदर रहना होगा । यह ऑब्जेक्ट नहीं जानता (और नहीं होना चाहिए) यह एक TripleAttackवस्तु द्वारा सजाया गया है । नतीजा यह है कि 3 आंसू एनिमेशन स्वतंत्र रूप से आगे बढ़ना है, क्योंकि है कर रहे हैं स्वतंत्र।
NauticalMile

मुझे इसे शब्दों में समझाने में मुश्किल समय आ रहा है, अगर कोई दूसरा व्यक्ति इसे लेना चाहता है, तो मेरे मेहमान बनें।
NauticalMile

जैसा कि इसे और अधिक कार्यात्मक भाषा में लागू करने के लिए, मैं इसके बारे में कुछ समय के लिए सोचूंगा और जब मैं तैयार हूं तो अपने जवाब में संशोधन करूंगा।
NauticalMile

1

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

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

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

Isaac has IsaacMutators:
--spoonbender which gives no stat change and: Tears are made homing
--MeatEater which give +1 health, +1 damage and: nothing
--MagicMirror which gives no stat change and: Tears are made reflecting

Tears have tearMutators:
--(depends on MeatEater) +1 damage and: nothing
--(depends on MagicMirror) no stat change and: +1 vector towards isaac
--(depnds on spoonbender) no stat change and: +1 vector towards enemytype

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


-5

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

जब दोनों आइटम मौजूद होते हैं, तो आप एक नई प्रकार की परिभाषा बनाकर इसके बारे में भी जा सकते हैं, लेकिन यह वास्तव में कनवल्शन में जोड़ता है:

if spoon bender and the inner eye then new spoon bender inner eye

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