2010-02-09 18 views
21

मैं एक साधारण गेम डिज़ाइन कर रहा हूं, जो जावा 2 डी और न्यूटनियन भौतिकी का उपयोग करता है। वर्तमान में अपने मुख्य "खेल लूप" तरह दिखता है:ओओओ तरीके से गेम डिज़ाइन

do { 
    for (GameEntity entity : entities) { 
    entity.update(gameContext); 
    } 

    for (Drawable drawable : drawables) { 
    drawable.draw(graphics2d); 
    } 
} while (gameRunning); 

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

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

विकल्प यहां मैं अब तक के बारे में सोचा गया है कर रहे हैं:

  • प्रत्येक इकाई है जहाँ से इकाई में ही निकाल सकते हैं यदि आवश्यक हो या अद्यतन खेल राज्य के लिए एक GameContext दर्रा (जैसे करने के लिए "नहीं चल" अगर खिलाड़ी मारे गए)।
  • केंद्र Game कक्षा में श्रोता के रूप में प्रत्येक GameEntity पंजीकृत करें और एक ईवेंट उन्मुख दृष्टिकोण लें; जैसे एक टक्कर के परिणामस्वरूप CollisionEvent टक्कर में दो प्रतिभागियों को निकाल दिया जाएगा।
+2

मुझे लगता है कि मैं अपने बग मिला - यह 'है, जबकि (gameRunning)' तुम वहाँ चाहते हैं –

उत्तर

14

मैं दो वाणिज्यिक खेल इंजन के साथ मिलकर काम किया है और वे एक समान पैटर्न का पालन करें:

  • वस्तुओं के बजाय पूरे इकाई (भौतिक, renderable, जो कुछ भी तरह) घटकों या एक खेल इकाई के पहलुओं का प्रतिनिधित्व । प्रत्येक प्रकार के घटक के लिए घटकों की एक विशाल सूची होती है, प्रत्येक इकाई उदाहरण के लिए एक घटक जिसमें घटक होता है।

  • 'गेम इकाई' प्रकार स्वयं ही एक अद्वितीय आईडी है। घटकों की प्रत्येक विशाल सूची में एक घटक आईडी (यदि कोई मौजूद है) देखने के लिए एक नक्शा है जो किसी इकाई आईडी से मेल खाता है।

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

    • आप स्वतंत्र रूप से हर संयोजन के लिए नए वर्गों लिख रहे हैं या जटिल विरासत पेड़ का उपयोग किए बिना कार्यक्षमता गठजोड़ कर सकते हैं:

    यहाँ इस दृष्टिकोण का लाभ हैं।

  • लगभग कोई कार्यक्षमता आप के बारे में सभी खेल संस्थाओं है कि आप एक खेल इकाई आधार वर्ग में डाल सकता है (क्या एक प्रकाश एक रेस कार या एक आकाश बॉक्स के साथ आम में है करता है यह मान सकते हैं नहीं है ?)

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

+0

@Evan: आपके उत्तर के लिए धन्यवाद। मैं आपसे पूछना चाहता था: इस उदाहरण में आप किसी इकाई को हटाने के तरीके को कैसे संभालेंगे? उदाहरण के लिए, मान लीजिए कि आपके पास एक पहलू कोलाइडेबल है, और आपका CollisionManager टकराव का पता लगाता है, जिससे इकाई को हटाया जाना चाहिए। संभवतः CollisionManager केवल इकाई के कोलाइडबल पहलू का संदर्भ देता है, और फिर विभिन्न सूचियों से इकाई के सभी ** पहलुओं (ड्रायबल, कोलाइडेबल इत्यादि) को हटाने के लिए आप किस दृष्टिकोण को लेते हैं? – Adamski

+1

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

6

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

हमारे पास एक अलग वस्तु में वास्तविक भौतिकी मॉडलिंग भी किया गया था जिसे फ्लाई पर बदला जा सकता था। यह हमें गुरुत्वाकर्षण, आदि के साथ आसानी से गड़बड़ कर देता है।

हमने ईवेंट संचालित कोड (श्रोता पैटर्न), और बहुत सारे और टाइमर के भारी उपयोग किए।

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

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

+0

धन्यवाद - यहां कुछ अच्छी सलाह दी गई है। – Adamski

+0

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

3

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

से अधिक सरलीकरण यहाँ उदाहरण नकल उतार सिर्फ अपनी बात कहने के लिए:

mainloop: 
    moveEntities() 
    resolveCollisions() [objects may "disappear"/explode here] 
    drawEntities()  [drawing before or after cleanEntitites() ain't an issue, a dead entity won't draw itself] 
    cleanDeadEntities() 

अब आप एक बुलबुला वर्ग है:

Bubble implements Drawable { 

handle(Needle needle) { 
    if (needle collide with us) { 
     exploded = true; 
    } 
} 

draw (...) { 
    if (!exploded) { 
     draw(); 
    } 
    } 
} 

तो, यकीन है कि, वहाँ एक मुख्य पाश है कि का ख्याल रखता है है संस्थाओं के बीच संदेशों को पारित करना लेकिन बबल और सुई के बीच टकराव से संबंधित तर्क निश्चित रूप से मुख्य गेम क्लास में नहीं है।

मुझे पूरा यकीन है कि आपके मामले में भी आंदोलन से संबंधित सभी तर्क मुख्य वर्ग में नहीं हो रहे हैं।

तो मैं आपके बयान में असहमत हूं कि आपने बोल्ड में लिखा है कि "सभी तर्क मुख्य वर्ग में होते हैं"।

यह बस सही नहीं है।

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

+0

धन्यवाद। मैं पूरी तरह से गेम लूप को खत्म करने की वकालत नहीं कर रहा था, बस इसे जितना संभव हो सके उतना सरल रखना ताकि आपने जो कहा है वह समझ में आता है। – Adamski

1

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

परिशिष्ट: आपको गेम के मॉडल को अलग रखने की आवश्यकता है, लेकिन आप उस मॉडल को आवश्यकतानुसार कई वर्गों में फिर से कारक बना सकते हैं।

2

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

मैंने इसे से कुछ युगल सीखा है।

+0

ग्रेट सामान - इसे जांच लेंगे। – Adamski

2

मैं इसे केवल एक उत्तर के रूप में पोस्ट कर रहा हूं क्योंकि मैं अभी तक अन्य पोस्ट पर टिप्पणी करने में सक्षम नहीं हूं।

इवान रोजर्स उत्कृष्ट जवाब देने के लिए एक परिशिष्ट के रूप में आप इन लेखों में रुचि हो सकती है:

http://www.gamasutra.com/blogs/MeganFox/20101208/6590/Game_Engines_101_The_EntityComponent_Model.php

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

संबंधित मुद्दे