थ्रेडिंग के बिना स्क्रिप्टिंग और सिनेमैटिक्स


12

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

def dramatic_scene(actors):
    alice = actors["alice"]
    bob = actors["bob"]

    alice.walk_to(bob)
    if bob.can_see(alice):
        bob.say("Hello again!")
    else:
        alice.say("Excuse me, Bob?")

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

मैंने माना कि प्रत्येक फंक्शन को एक एक्शन बनाना है - alice.walk_to(bob)एक ऑब्जेक्ट को एक कतार पर धकेला जाएगा, जो ऐलिस बॉब के पहुंचने के बाद, जहां भी वह था, पॉपअप हो जाएगा। यह अधिक सूक्ष्म रूप से टूट गया है: ifशाखा का तुरंत मूल्यांकन किया जाता है, इसलिए बॉब ऐलिस को बधाई दे सकता है, भले ही उसकी पीठ उसकी ओर हो।

थ्रेड बनाने के बिना अन्य इंजन / लोग स्क्रिप्टिंग को कैसे संभालते हैं? मैं गैर-गेम-देव क्षेत्रों में देखना शुरू कर रहा हूं, जैसे कि jQuery एनीमेशन चेन, विचारों के लिए। ऐसा लगता है कि इस तरह की समस्या के लिए कुछ अच्छे पैटर्न होने चाहिए।


1
प्रश्न के लिए +1 लेकिन विशेष रूप से "पायथन (उर्फ स्यूडोकोड)" :) के लिए
विकेट

अजगर एक महाशक्ति होने की तरह है।
19

जवाबों:


3

जिस तरह पांडा कुछ ऐसा करता है वह कॉलबैक के साथ होता है। ब्लॉक करने के बजाय यह कुछ ऐसा होगा

def dramatic_scene(actors):
    alice = actors["alice"]
    bob = actors["bob"]

    def cb():
        if bob.can_see(alice):
            bob.say("Hello again!")
        else:
            alice.say("Excuse me, Bob?")
    alice.walk_to(bob, cb)

एक पूर्ण-पूर्ण कॉलबैक होने से आप इन प्रकार की घटनाओं को जितनी गहराई से चाहते हैं, उतने चेन कर सकते हैं।

संपादित करें: इस शैली के लिए बेहतर सिंटैक्स के बाद से जावास्क्रिप्ट उदाहरण:

function dramatic_scene(actors) {
    var alice = actors.alice;
    var bob = actors.bob;
    alice.walk_to(bob, function() {
        if(bob.can_see(alice)) {
            bob.say('Hello again!');
        } else {
            alice.say('Excuse me, Bob?');
        }
     });
}

यह +1 के लिए पर्याप्त काम करता है, मुझे लगता है कि सामग्री डिजाइन करने के लिए यह गलत है। मैं अपने अंत पर कुछ अतिरिक्त काम करने को तैयार हूं ताकि स्क्रिप्ट सरल और स्पष्ट दिखें।
19

1
@ योजना: वास्तव में यह तरीका बेहतर है, क्योंकि यहां एक ही स्क्रिप्ट में आप कई अभिनेताओं को एक ही समय पर चलना शुरू करने के लिए कह सकते हैं।
बार्ट वैन ह्युकेलोम

ऊ, अच्छा बिंदु।
ओज्रक

हालाँकि पठनीयता में सुधार के लिए, कॉलबैक परिभाषा को walk_to () कॉल के अंदर नेस्ट किया जा सकता है, या उसके बाद डाल दिया जा सकता है (दोनों के लिए: यदि भाषा समर्थन करती है) तो कोड जिसे बाद में कहा जाता है, स्रोत में बाद में देखा जाता है।
बार्ट वैन ह्युकेलोम

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

13

यहां आप जिस शब्द को खोजना चाहते हैं, वह है " कोराउटाइन्स " (और आमतौर पर भाषा कीवर्ड या फ़ंक्शन का नाम yield)।

Coroutines प्रोग्राम घटक हैं जो कुछ स्थानों पर निष्पादन और निलंबन को फिर से शुरू करने के लिए कई प्रवेश बिंदुओं की अनुमति देने के लिए सबरूटीन्स को सामान्य करते हैं।

कार्यान्वयन आपकी भाषा पर सबसे पहले निर्भर करेगा। एक खेल के लिए आप चाहते हैं कि कार्यान्वयन जितना संभव हो उतना हल्का वजन हो (थ्रेड्स या फाइबर से हल्का)। विकिपीडिया पृष्ठ (लिंक्ड) में विभिन्न भाषा-विशिष्ट कार्यान्वयन के लिए कुछ लिंक हैं।

मैंने सुना है कि लुआ ने कोरटाइन के लिए अंतर्निहित समर्थन किया है। तो GameMonkey करता है।

अवास्तविक इसे "राज्यों" और "अव्यक्त कार्यों" के रूप में लागू करता है।

यदि आप C # का उपयोग करते हैं तो आप Nick Gravelyn के इस ब्लॉग पोस्ट को देख सकते हैं।

इसके अतिरिक्त "एनीमेशन चेन" विचार, जबकि एक ही चीज़ नहीं, एक ही समस्या का एक व्यावहारिक समाधान है। निक ग्रेवलिन का एक C # कार्यान्वयन भी है ।


नाइस कैच, टेट्रैड;)
एंड्रयू रसेल

यह वास्तव में अच्छा है, लेकिन मुझे यकीन नहीं है कि यह मुझे वहां 100% मिलता है। ऐसा लगता है कि कॉरटाइन्स आपको कॉलिंग विधि तक उपज देते हैं, लेकिन मैं एक लुआ लिपि से उपजाने का एक तरीका चाहता हूं, जिस तरह से सी # कोड को स्टैक अप किया जाता है, जबकि (वॉक_टो ()! = किया गया) {उपज}।
ओजक्र सिप

@ योजना: मुझे लूआ के बारे में पता नहीं है, लेकिन यदि आप निक ग्रेवेलिन के सी # पद्धति का उपयोग कर रहे हैं, तो आप एक प्रतिनिधि (या एक ऑब्जेक्ट जिसमें एक हो सकता है) को लौटा सकते हैं जो आपके स्क्रिप्ट प्रबंधक को चेक करने के लिए सशर्त रखता है (निक का कोड बस एक बार लौटता है जो कि सशर्त रूप से एक सशर्त है)। तुम भी अव्यक्त कार्य स्वयं प्रतिनिधि को वापस कर सकते थे, इसलिए आप लिख सकते थे: yield return walk_to();अपनी लिपि में।
एंड्रयू रसेल

C # में यील्ड कमाल है, लेकिन मैं सरल, हार्ड-टू-मेस-अप स्क्रिप्टिंग के लिए अपने समाधान का अनुकूलन कर रहा हूं। मेरे पास उपज की तुलना में कॉलबैक की व्याख्या करने का एक आसान समय होगा, इसलिए मैं दूसरे उत्तर को स्वीकार करूंगा। अगर मैं कर सकता तो मैं +2 था।
3

1
आपको आम तौर पर उपज कॉल की व्याख्या करने की आवश्यकता नहीं है - आप उदाहरण के लिए, "walk_to" फ़ंक्शन में लपेट सकते हैं।
काइलोटन

3

पिरोया नहीं जा रहा है स्मार्ट है।

अधिकांश गेम इंजन प्रत्येक चरण को चलाने वाले मेमोरी में सामान के साथ मॉड्यूलर चरणों की एक श्रृंखला के रूप में काम करते हैं। आपके 'उदाहरण के लिए चलें' के लिए, आपके पास आमतौर पर एक AI चरण होता है, जहाँ आपके चलने वाले पात्र एक ऐसी स्थिति में होते हैं जहाँ उन्हें दुश्मनों को मारने की तलाश में नहीं होना चाहिए, एक एनीमेशन मंच जहाँ उन्हें एनीमेशन X, भौतिकी मंच (या) चलना चाहिए सिमुलेशन चरण) जहां उनकी वास्तविक स्थिति अपडेट की जाती है, आदि।

आपके उदाहरण के ऊपर, 'ऐलिस' एक ऐसा अभिनेता है जो टुकड़ों से बना होता है, जो इन चरणों में से कई में रहता है, इसलिए एक अवरुद्ध अभिनेता .walk_to कॉल (या एक coroutine जिसे आप अगले कॉल करते हैं) (एक बार प्रति फ्रेम पर) शायद उचित संदर्भ नहीं होगा बहुत सारे निर्णय लेने के लिए।

इसके बजाय, एक 'start_walk_to' फ़ंक्शन शायद कुछ ऐसा करेगा:

def start_cutscene_walk_to(actor,target):
    actor.ai.setbrain(cutscene_brain)
    actor.physics.nocoll = 1
    actor.anims.force_anim('walk')
    # etc.

फिर, आपका मुख्य लूप अपनी एआई टिक, इसकी भौतिकी टिक, इसकी एनीमेशन टिक, और इसकी कटक टिक, और कटकीन आपके इंजन में प्रत्येक सबसिस्टम के लिए स्थिति को अपडेट करता है। Cutscene प्रणाली को निश्चित रूप से ट्रैक करना चाहिए कि उसके प्रत्येक cutscenes क्या कर रहे हैं, और एक coroutine चालित प्रणाली के लिए कुछ रैखिक और निर्धारक जैसे एक custscene समझ में आ सकता है।

इस प्रतिरूपता का कारण यह है कि यह सिर्फ चीजों को अच्छा और सरल रखता है, और कुछ प्रणालियों (जैसे भौतिकी और एआई) के लिए, आपको चीजों को ठीक से हल करने और एक सुसंगत स्थिति में रखने के लिए एक ही समय में हर चीज की स्थिति को जानना होगा। ।

उम्मीद है की यह मदद करेगा!


मुझे पसंद है कि आप क्या करने जा रहे हैं, लेकिन मैं वास्तव में अभिनेता के मूल्य के बारे में दृढ़ता से महसूस करता हूं। वालक_तो ([एक अन्य अभिनेता, एक निश्चित स्थिति, या यहां तक ​​कि एक फ़ंक्शन जो एक स्थिति देता है])। मेरा लक्ष्य सरल, समझने योग्य उपकरण प्रदान करना है और खेल की सामग्री निर्माण भाग से सभी जटिलता को दूर करना है। आपने मुझे यह महसूस करने में भी मदद की कि मैं वास्तव में चाहता हूं कि प्रत्येक स्क्रिप्ट को एक परिमित राज्य मशीन के रूप में माना जाए।
ओजार्क

मैं खुशी से मदद कर सकता है! मुझे लगा कि मेरी प्रतिक्रिया एक छोटा विषय था :) निश्चित रूप से अपने लक्ष्यों को पूरा करने के लिए एक अभिनेता के मूल्य के साथ सहमत हूँ। मैं अपने कार्यान्वयन के बारे में सुनने के लिए उत्सुक हूं।
एरोन ब्रैडी

ऐसा लगता है कि मैं कॉलबैक और जंजीर कार्यों के एक jQuery- शैली के मिश्रण के साथ जाऊंगा। स्वीकृत उत्तर देखें;)
3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.