एडवेंचर गेम्स में विभिन्न राज्यों को कोड करना


12

मैं एक साहसिक खेल की योजना बना रहा हूं, और यह नहीं जान सकता कि कहानी प्रगति की स्थिति के आधार पर एक स्तर के व्यवहार को लागू करने का सही तरीका क्या है।

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

मैंने शुरू में NPC को क्या कहना चाहिए या क्या पाया जा सकता है, यह तय करने के लिए शुरू में एक स्विच {} स्टेटमेंट का उपयोग करने के बारे में सोचा और एक वैश्विक game_state वैरिएबल की स्थिति की जांच करने के बाद ही खोज उद्देश्यों को इंटरैक्ट कर सकने योग्य बनाया। लेकिन मुझे एहसास हुआ कि किसी वस्तु के व्यवहार को बदलने के लिए मैं जल्दी से विभिन्न गेम स्टेट्स और स्विच-केस में चला जाऊंगा। यह स्विच स्टेटमेंट डिबग करने के लिए बड़े पैमाने पर कठिन होगा, और मुझे लगता है कि यह एक स्तर संपादक में उपयोग करने के लिए भी कठिन हो सकता है।

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

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

मेरे सभी तरीके इतने अकुशल लगते हैं, इसलिए मेरे सवाल को सुनाने के लिए, कहानी प्रगति की स्थिति के आधार पर एक स्तर के व्यवहार को लागू करने के लिए एक बेहतर या मानकीकृत तरीका है?

पुनश्च: मेरे पास अभी तक एक स्तर का संपादक नहीं है - जेएमई एसडीके जैसी किसी चीज का उपयोग करने या अपना खुद का बनाने की सोच।

जवाबों:


9

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

एक राज्य इंटरफ़ेस कैसा दिखेगा (पूरी तरह से बना हुआ - सिर्फ इस योजना को आपके नियंत्रण के स्तर को स्पष्ट करने के लिए):

interface NPCState {
    Scene whereAmI(NPC o);
    String saySomething(NPC o);
}

और दो कार्यान्वयन कक्षाएं:

class Busy implements NPCState {
    Scene whereAmI(NPC o) {
        return o.getWorkScene();
    }
    String saySomething(NPC o) {
        return "Can't talk now, I'm busy!";
    }
}

class Available implements NPCState {
    Scene whereAmI(NPC o) {
        return TAVERN;
    }
    String saySomething(NPC o) {
        String[] choices = o.getRandomChat();
        return choices[RANDOM.getInt(choices.length)];
    }
}

और स्विचिंग स्टेट्स:

// The time of day passed from "afternoon" to "evening"
NPCState available = new Available();
for ( NPC o : list ) {
    Scene oldScene = o.state.whereAmI(o);
    o.state = available;
    Scene newScene = o.state.whereAmI(o);
    moveGameObject(o, oldScene, newScene);
    ...

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

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

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


हाँ, आप इस स्टेट डिज़ाइन पैटर्न को मेरे द्वारा वर्णित साहचर्य सरणी के साथ जोड़ सकते हैं। आप यहाँ वर्णित के रूप में राज्य की वस्तुओं को कोड कर सकते हैं, और फिर विभिन्न ऐच्छिक वस्तुओं के बीच चयन कर सकते हैं जैसा कि मैंने सुझाव दिया था।
झनक

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

तो जैसा कि मैं इसे समझता हूं, वहाँ एक-से-एक मैपिंग btwn NPCState और GameState है। तब मैंने एनपीसी को एक सरणी में रखा और एक गेम स्टेट चेंज होने पर नए NPCState को असाइन करते हुए इसे पुन: व्यवस्थित किया। NPCState को यह जानने में सक्षम होना चाहिए कि उसे भेजे जाने वाले प्रत्येक NPC को कैसे संभालना है, इसलिए अनिवार्य रूप से NPCState में किसी दिए गए राज्य के लिए सभी NPC का व्यवहार है? मुझे पसंद है कि सभी व्यवहार एक ही NPCState में सफाई से स्टोर होते हैं, जो साफ-साफ खेल संपादक के कार्यान्वयन के लिए मैप करता है, लेकिन यह थोड़े NPCState को बहुत बड़ा बनाता है।
कार्डिन

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

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

2

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

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

if (state in behaviors) {
  behaviors[state]();
}

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

1
खैर यह मेरा प्रारंभिक विचार था, लेकिन mgibsonbr के उत्तर को देखने के बाद मैंने महसूस किया कि आप विभिन्न bevaviors को अलग-अलग कक्षाओं के रूप में कोड कर सकते हैं और फिर डेटा फ़ाइल में सिर्फ यह कह सकते हैं कि कौन से व्यवहार वर्ग किस राज्य के साथ चलते हैं। उस डेटा को रनटाइम पर एक सहयोगी सरणी में लोड करें।
jhocking

ओह .. हाँ, यह निश्चित रूप से सरल है! : D लुआ हाहा की तरह कुछ एम्बेड करने के परिदृश्य की तुलना में ..
कार्डिन

2

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

उल्लेखित राज्य डिजाइन पैटर्न के बजाय मैं एक रणनीति-पैटर्न का उपयोग करूंगा।

यदि किसी npc के पास वर्ण और m स्थितियों के साथ बातचीत करने के लिए n तरीके हैं जहाँ वह हो सकता है, तो अधिकतम (m * n) +1 कक्षाएं हैं जिन्हें आपको डिज़ाइन करना है। रणनीति-पैटर्न का उपयोग करके आप n + m + 1 वर्गों के साथ समाप्त हो जाएंगे, लेकिन इन रणनीतियों का उपयोग अन्य npcs द्वारा भी किया जा सकता है।

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


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

मैंने इन दो पैटर्नों का इस्तेमाल कुछ ही बार किया है इसलिए मैं आपको विपक्ष के बारे में बताने में सक्षम नहीं हूं: - / लेकिन मुझे लगता है कि यह एकल जिम्मेदारी के मामले में अच्छा है और हर रणनीति का परीक्षण करने की उपलब्धता :) यह भ्रमित हो सकता है अगर आपकी कई अलग-अलग वर्गों में एक रणनीति का उपयोग करना और आप हर वर्ग को ढूंढना चाहते हैं जो इसका उपयोग करता है।
TOAOGG

0

दिए गए सभी दृष्टिकोण मान्य हैं। यह उस स्थिति पर निर्भर करता है जो आप किसी भी क्षण में हैं। कई एडवेंचर्स या MMO इनमें से एक संयोजन का उपयोग करते हैं।

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

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

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

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

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