Cave: शुरुआत गाइड

Back to Learn

Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

अब जब आपने देखा है कि Cave में पात्र और एनीमेशन कैसे काम करते हैं, तो आइए एक कदम पीछे हटें और उस स्क्रिप्टिंग सिस्टम को समझें जो आमतौर पर सब कुछ आपस में जोड़ता है: Python

Cave में Python का उपयोग gameplay व्यवहार, संपादक टूल, UI callbacks, animation callbacks, timeline events, और छोटी-छोटी कस्टम लॉजिक लिखने के लिए किया जाता है जो एक अंतर्निहित घटक के रूप में मौजूद होने के लिए बहुत विशिष्ट होंगे। Cave का उपयोग करने से पहले आपको एक उन्नत Python प्रोग्रामर बनने की आवश्यकता नहीं है, लेकिन Cave स्क्रिप्ट का मूल रूप समझना बहुत उपयोगी है।

इस पाठ में, आप सीखेंगे:

  • Cave में Python का उपयोग किसलिए किया जाता है।
  • Python Script assets और Python Components कैसे एक साथ काम करते हैं।
  • start() और update() क्या करते हैं।
  • स्क्रिप्ट से वर्तमान entity को कैसे एक्सेस करें।
  • एक entity से घटकों को कैसे प्राप्त करें।
  • Python Component या Python Code Component का उपयोग कब करें।

लक्ष्य संपूर्ण Python भाषा सिखाना नहीं है। लक्ष्य यह है कि जब आप Cave स्क्रिप्ट को खोलें, तो वे समझने योग्य लगें।

Python कहाँ सीखा जाए?

यदि आप Python में कोड करना नहीं जानते हैं, तो Uniday Studio वास्तव में Python पर निःशुल्क सीखने के quests भी प्रदान करता है। सभी विकल्प देखने के लिए uniday.studio/learn पर जाएं या यहाँ से शुरू करें:

इस अनुभाग के लिए, हम मानेंगे कि आपको उन दो सीखने के quests में संभाले गए विषयों पर पहले से समझ है।


Cave में Python का उपयोग किसलिए किया जाता है

Cave में, Python वह स्क्रिप्टिंग परत है जिसे आप उपयोग करते हैं जब किसी गेम ऑब्जेक्ट को व्यवहार की आवश्यकता होती है।

उदाहरण के लिए, Python का उपयोग किया जा सकता है:

  • एक खिलाड़ी या दुश्मन को गतिमान करने के लिए।
  • एक दरवाजा खोलने के लिए।
  • एक एनीमेशन खेलने के लिए।
  • एक ध्वनि को ट्रिगर करने के लिए।
  • एक टाइमलाइन शुरू करने के लिए।
  • दृश्यों को बदलने के लिए।
  • UI तत्व को अपडेट करने के लिए।
  • कस्टम संपादक टूल बनाने के लिए।

बुनियादी रूप से, आप अपने खेल की सभी लॉजिक बनाने के लिए Python स्क्रिप्ट लिख सकते हैं।

इसलिए, जब आप Cave में Python लिखते हैं, तो आप आमतौर पर अलग-थलग कोड नहीं लिख रहे होते हैं। आप एक entity को नियंत्रित करने वाली लॉजिक लिख रहे होते हैं और उस entity से जुड़े घटकों से संवाद कर रहे होते हैं।

स्क्रिप्ट एसेट्स और Python घटक

Python कोड आमतौर पर एक Python Script एसेट के भीतर रहता है।

image.png

फिर, उस स्क्रिप्ट को एक दृश्य में चलाने के लिए, आप एक Python Component को एक entity में जोड़ते हैं और चुनते हैं कि स्क्रिप्ट से कौन सा क्लास निष्पादित किया जाना चाहिए।

इसे इस तरह समझें:

भाग यह क्या करता है
Python Script एसेट कोड को स्टोर करता है।
Python Component एक entity पर उस स्क्रिप्ट से एक क्लास को चलाता है।
Entity वह ऑब्जेक्ट जो स्क्रिप्ट द्वारा नियंत्रित होता है।
cave.Component क्लास वह वास्तविक व्यवहार जो आपने लिखा।

उदाहरण के लिए, आपके पास Door Controller नामक एक स्क्रिप्ट एसेट हो सकता है। इसके भीतर, आपके पास DoorController नामक एक क्लास हो सकता है जो cave.Component से विरासत में मिली है। फिर आप अपने दरवाजा entity में एक Python Component जोड़ते हैं और उस क्लास का चयन करते हैं।

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

एक न्यूनतम Cave घटक

एक बुनियादी Cave Python घटक इस तरह दिखता है:

import cave

class MyComponent(cave.Component):
    def start(self, scene):
        print("The component started!")

    def update(self):
        pass

यहाँ कुछ महत्वपूर्ण विवरण हैं:

  • import cave आपकी स्क्रिप्ट को Cave की Python API तक पहुँच देती है।
  • class MyComponent(cave.Component) एक घटक क्लास बनाती है जिसे Cave चला सकता है।
  • start(self, scene) तब चलता है जब घटक शुरू होता है।
  • update(self) हर फ्रेम में चलता है जब घटक सक्रिय होता है।

नाम MyComponent कुछ भी हो सकता है, लेकिन वास्तविक परियोजनाओं में आपको स्पष्ट नाम जैसे DoorController, EnemyAI, Checkpoint, या PlayerHealth का उपयोग करना चाहिए।

जीवन चक्र विधियाँ

Cave कुछ विधियों को स्वचालित रूप से तब कॉल करता है जब आपका घटक चल रहा होता है।

सबसे सामान्य हैं:

विधि यह कब चलती है सामान्य उपयोग
start(self, scene) जब घटक शुरू होता है। संदर्भ प्राप्त करना, गुण पढ़ना, चर तैयार करना।
firstUpdate(self) हमेशा प्रत्येक Entity Component की शुरुआत विधि के बाद, पहले अपडेट में। अन्य घटकों के आरंभ होने पर निर्भर चर बनाना।
update(self) प्रत्येक फ्रेम, यदि दृश्य स्थगित नहीं है। गति, इनपुट, टाइमर्स, स्थिति जांच।
pausedUpdate(self) प्रत्येक फ्रेम, यदि दृश्य स्थगित है। स्थगित लॉजिक।
end(self, scene) जब घटक समाप्त होता है। आवश्यकता होने पर साफ करना।

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

हम editorUpdate और lateUpdate विधियों के पास भी हैं, लेकिन हम उन्हें यहाँ नहीं देखेंगे क्योंकि वे थोड़े अधिक उन्नत हैं।

वर्तमान Entity का एक्सेस करना

Cave घटक के भीतर, self.entity वह entity है जो Python Component का मालिक है।

यह Cave स्क्रिप्टिंग में सबसे महत्वपूर्ण विचारों में से एक है। स्क्रिप्ट अपनेआप दृश्य में तैरती नहीं है। यह एक entity से संबंधित है।

यहाँ एक सरल उदाहरण है:

import cave

class DoorController(cave.Component):
    def start(self, scene):
        self.transform = self.entity.getTransform()
        self.isOpen = False

    def update(self):
        pass

इस स्क्रिप्ट में:

  • self.entity दरवाजे की entity है।
  • self.entity.getTransform() दरवाजे का Transform Component प्राप्त करता है।
  • self.isOpen एक चर है जिसका उपयोग स्क्रिप्ट द्वारा किया जाता है ताकि याद रहे कि दरवाजा खुला है या नहीं।

आप इस पैटर्न का उपयोग हर समय करेंगे। पहले आप entity को प्राप्त करें, फिर आवश्यक घटक या चाइल्ड entities प्राप्त करें, और फिर उनका उपयोग अपनी लॉजिक में करें।

अन्य घटक प्राप्त करना

किसी entity को नियंत्रित करने के लिए, आपको सामान्यतः एक या एक से अधिक घटकों को उससे प्राप्त करने की आवश्यकता होती है।

उदाहरण के लिए, एक खिलाड़ी स्क्रिप्ट यह प्राप्त कर सकती है:

  • Transform घटक को entity को स्थानांतरित या घुमाने के लिए।
  • Character घटक को चरित्र गति को संभालने के लिए।
  • एक चाइल्ड मैश entity से Animation घटक को एनीमेशन खेलने के लिए।
  • Audio घटक को लूपिंग ध्वनि चलाने के लिए।

यहाँ एक छोटा उदाहरण है:

import cave

class SimpleMover(cave.Component):
    def start(self, scene):
        self.transform = self.entity.getTransform()
        self.speed = 2.0

    def update(self):
        self.transform.move(0, 0, self.speed * cave.getDeltaTime(), local=True)

यह हर फ्रेम में entity को आगे बढ़ाता है।

महत्वपूर्ण भाग है cave.getDeltaTime()। चूंकि update() हर फ्रेम में चलता है, गति को डेल्टा समय से गुणा करना गति की गति को स्थिर रखता है, भले ही फ्रेम दर बदल जाए।

कस्टम गुण पढ़ना

पहले परीक्षण के लिए हार्डकोडेड मान ठीक हैं, लेकिन वास्तविक गेम ऑब्जेक्ट्स के लिए संपादनीय गुण आमतौर पर बेहतर होते हैं।

उदाहरण के लिए, इसके बजाय लिखें:

self.speed = 2.0

आप entity गुणों से मान को पढ़ सकते हैं:

self.speed = self.entity.properties.get("speed", 2.0)

इसका मतलब है:

  • यदि entity का speed गुण है, तो इसे उपयोग करें।
  • यदि यह नहीं है, तो 2.0 को डिफ़ॉल्ट मान के रूप में उपयोग करें।

यह पुन: प्रयोज्य स्क्रिप्टों के लिए बहुत उपयोगी है। आप एक SimpleMover स्क्रिप्ट बना सकते हैं और इसे कई entities पर उपयोग कर सकते हैं, प्रत्येक के पास अलग गति होती है।

उदाहरण के लिए:

Entity speed गुण
Slow Platform 1.0
Fast Platform 4.0
Moving Hazard 7.0

स्क्रिप्ट वही है, लेकिन प्रत्येक entity के अनुसार व्यवहार बदलता है।

वैकल्पिक रूप से, आप घटक के लिए स्वयं के लिए स्थानीय रूप से परिवर्तनीय चर बना सकते हैं बजाय इसके कि entity के गुणों पर निर्भर रहें। जब आप इस तरह एक चर बनाते हैं:

import cave

class PlatformMover(cave.Component):
    # यह स्थानीय होगा:
    speed = 2.0

    def start(self, scene: cave.Scene):
        pass

    def update(self):
        events = cave.getEvents()

speed चर हर घटक उदाहरण के लिए स्थानीय रूप से परिवर्तनीय होगा:

image.png


चाइल्ड entities प्राप्त करना

कई Cave ऑब्जेक्ट्स छोटे पदानुक्रमों के रूप में बनाए जाते हैं।

खिलाड़ी टेम्पलेट एक अच्छा उदाहरण है। मूल Player entity में चरित्र भौतिकी और लॉजिक होता है, जबकि चाइल्ड Mesh entity में दृश्य चरित्र मैश और Animation Component होता है।

इसलिए, यदि मूल खिलाड़ी entity पर एक स्क्रिप्ट एनीमेशन को चलाना चाहती है, तो पहले इसे चाइल्ड मैश entity प्राप्त करने की आवश्यकता होती है:

import cave

class PlayerAnimationExample(cave.Component):
    def start(self, scene):
        self.mesh = self.entity.getChild("Mesh")
        self.animator = self.mesh.get("Animation")

    def update(self):
        self.animator.playByName("p-idle", blend=0.2, loop=True)

यह वही पैटर्न है जिसका उपयोग डिफ़ॉल्ट खिलाड़ी नियंत्रक द्वारा किया जाता है:

  1. चाइल्ड entity प्राप्त करें।
  2. उस चाइल्ड से घटक प्राप्त करें।
  3. जब आवश्यक हो, घटक का उपयोग करें।

जब आप उस पैटर्न को समझ लेते हैं, तो कई Cave स्क्रिप्ट पढ़ना बहुत आसान हो जाता है।

getChild विधि में एक वैकल्पिक "recursive" पैरामीटर होता है, जो डिफ़ॉल्ट रूप से True होता है। यदि True है, तो यह सभी Entity चाइल्ड को क्वेरी करेगा, चाइल्ड के चाइल्ड सहित, जब तक कि यह अनुरोधित नाम से Entity नहीं ढूंढ लेता।

दृश्य entities प्राप्त करना (दृश्य क्वेरी)

जब आप एक खेल बना रहे हैं, तो यह बहुत संभव है कि आपको दृश्य में अन्य entities प्राप्त करने की आवश्यकता होगी। तो चलिए इसे अन्वेषण करते हैं। पहला कदम दृश्य को प्राप्त करना है, और Cave में, आपके पास इसे करने के लिए दो तरीके हैं:

# सक्रिय दृश्य लौटाता है:
scene = cave.getScene()

# दृश्य लौटाता है जिसमें यह एंटिटी मौजूद है:
scene = self.entity.getScene()

सुविधा के लिए, cave.Component के start और end मेथड्स को भी सीन के रूप में एक पैरामीटर प्राप्त होता है, क्योंकि यह बहुत संभावित है कि आप इन्हें उन मेथड्स में उपयोग करेंगे। स्थानीय कोड जैसे Python Code Component के लिए, आपके द्वारा डिफ़ॉल्ट रूप से परिभाषित scene वेरिएबल भी है जिसे आप जादुई रूप से "केवल इसका उपयोग करें" और इसे काम करने की उम्मीद कर सकते हैं।

एक बार जब आप दृश्य प्राप्त कर लेते हैं, तो आप निम्नलिखित कोड का उपयोग करके अपने नाम से एक विशेष Entity प्राप्त कर सकते हैं:

watchtower = scene.get("Watch Tower 01")

Cave दृश्य श्रेणी में आपके लिए अन्य दृश्य क्वेरी करने के लिए बहुत सारे अन्य मेथड प्रदान करता है। आप रे कैस्ट, गोला कैस्ट कर सकते हैं, संपर्क बॉक्स या गोले की जांच कर सकते हैं, बुनियादी टकराव क्वेरी के लिए, या यहां तक कि सभी एंटिटीज़, सभी रूट एंटिटीज़, विशिष्ट टैग वाली सभी एंटिटीज़, विशिष्ट गुणों वाली सभी एंटिटीज़, या विशिष्ट नाम वाली एंटिटीज़ प्राप्त कर सकते हैं, आदि। इसलिए Python API की जांच करना उचित है।

सदैव यह याद रखें कि आपका क्वेरी कुछ मान्य वापस कर रहा है या नहीं। उदाहरण के लिए:

# गैर-मौजूद एंटिटी की क्वेरी:
ent = scene.get("This Entity Doesnt Exist")

if ent is None:
    print("अमान्य एंटिटी!")

एंटिटी घटक प्राप्त करना

एक बार जब आपके पास एक विशेष एंटिटी होती है और आप यह जांचते हैं कि यह ज्ञात नहीं है, तो यह समझना एक अच्छा विचार है कि आप इससे विशिष्ट घटक कैसे प्राप्त कर सकते हैं।

एंटिटी में एक विशिष्ट मेथड होती है जिसे आप घटक का नाम एक स्ट्रिंग के रूप में पारित कर सकते हैं और यह स्वचालित रूप से एंटिटी का उपयोग करके देखेगा कि क्या आपकी खोज के साथ मिलाने वाला कोई घटक है:

animator = self.entity.get("Animation Component")

आपके जीवन को आसान बनाने के लिए, यदि एक घटक का नाम "Component" शब्द के साथ समाप्त होता है, जो बहुत सामान्य है, तो आप इस मेथड में घटक का नाम लिखते समय इस अंत को पूरी तरह से छोड़ सकते हैं। आप यह भी चुन सकते हैं कि आप मल्टी-वर्ड घटक नामों में व्हाइट स्पेस शामिल करना चाहते हैं या सब कुछ एक साथ रखना चाहते हैं।

उदाहरण के लिए, यदि आप एक एंटिटी से Rigid Body Component प्राप्त करना चाहते हैं, हालाँकि इसका Python नाम RigidBodyComponent है, तो नीचे दिए गए सभी विकल्प काम करेंगे:

rb = self.entity.get("Rigid Body")
rb = self.entity.get("RigidBody")
rb = self.entity.get("Rigid Body Component")
rb = self.entity.get("RigidBodyComponent")
rb = self.entity.get("RigidBody Component")

चूंकि Python बहुत टाइप किया हुआ नहीं है, Cave में यह एक अच्छे प्रोग्रामिंग प्रैक्टिस है कि आप घटक प्रकार के लिए एक प्रकार का संकेत प्रदान करें, जो नीचे दिए गए तरीके से किया जा सकता है। इस मामले में, आपको पूर्ण घटक नाम शामिल करने की आवश्यकता है, क्योंकि यह एक Python अर्थविज्ञान है:

rb : cave.RigidBodyComponent = self.entity.get("Rigid Body")

इससे IntelliSense बाहरी संपादकों जैसे कि Visual Studio Code में काम करता है या यहां तक कि उस अंतर्निहित ऑटो-कंप्लीट का उपयोग करता है जो Cave Engine आपको इसके एंबेडेड स्क्रिप्ट एडिटर में प्रदान करता है।

Transform Component के लिए, चूंकि यह सबसे सामान्य घटक प्रकारों में से एक है और आप इसे अक्सर क्वेरी करेंगे, एंटिटी के पास इसके प्रमुख Transform प्राप्त करने के लिए एक स्वदेशी मेथड है:

transf = self.entity.getTransform()

self.entity.getTransform() को कॉल करके इसे प्राप्त करना self.entity.get("Transform") को कॉल करने के समान परिणाम प्रदान करता है, लेकिन पहला विकल्प तेज और अधिक अनुकूलित है।

यदि एक एंटिटी में उसी प्रकार के कई घटक होते हैं, तो यह पहले मेल को लौटाएगा, लेकिन कभी-कभी आप सभी मेल चाहते हैं। उदाहरण के लिए, एक मल्टी-मटेरियल मेष जो Cave में एक एंटिटी द्वारा कई मेष घटकों के रूप में दर्शाया जाएगा, आप सभी मेष घटकों को प्राप्त करने के लिए चाहते हैं। और इसके लिए, आप getAll मेथड का उपयोग कर सकते हैं:

meshCmps = self.entity.getAll("Mesh")

# सभी सामग्रियों को एक चमकदार में बदलना:
for meshCmp in meshCmps:
    meshCmp.material.setAsset("Glowing Material")

एंटिटी Python घटक प्राप्त करना

अब हम जानते हैं कि स्वदेशी Cave घटक कैसे प्राप्त करें, लेकिन अगर आप एक एंटिटी से एक घटक प्राप्त करना चाहते हैं जिसे आपने Python का उपयोग करके कस्टम रूप से लिखा है?

इसके लिए, आपको getPy नामक एक विशेष मेथड की आवश्यकता होती है, और यह उसी तरह काम करता है जैसे नियमित get मेथड, सिवाय इसके कि यह भी Python घटकों को वापस करता है:

myCmp = self.entity.getPy("MyCustomComponent")

यह Cave को यथासंभव तेज़ बनाने के लिए आंतरिक अनुकूलन के कारण एक विशेष मेथड की आवश्यकता है।

एक बार जब आपके पास आपका कस्टम Python घटक होता है, तो आप इसके द्वारा बनाए गए वेरिएबल्स और मेथड्स को स्वतंत्र रूप से एक्सेस कर सकते हैं:

myCmp = self.entity.getPy("MyCustomComponent")

# Python वेरिएबल्स बदलना:
myCmp.customValue = 10

# कस्टम मेथड्स कॉल करना:
myCmp.doSomething()
myCmp.applyDamage(10)

Python Code Component

नियमित Python Component के अलावा, Cave में एक Python Code Component भी है। Python Code Component त्वरित स्क्रिप्टों के लिए उपयोगी है जो सीधे एंटिटी पर लिखी जाती हैं, बिना पहले एक अलग Python Script एसेट बनाए।

यह सभी अन्य मेथड्स रखता है, और अंतर यह है कि Python कोड घटक में, आप Python स्क्रिप्ट को सीधे घटक के भीतर लिखते हैं, और यह मॉड्यूलर नहीं होती और पुन: प्रयोज्य नहीं होती। इसलिए अगर आप एंटिटी की एक प्रति बनाते हैं, तो यह भी उसमें स्क्रिप्ट की एक प्रति बनाएगा। लेकिन कभी-कभी, यह कुछ सरल तर्क बनाने का एक तेज़ तरीका हो सकता है, जैसे एक घूमता हुआ सिक्का।

यह अच्छे लिए है:

  • त्वरित परीक्षण।
  • छोटे कॉलबैक।
  • एक बार की व्यवहार।
  • प्रोटोटाइप।

यह बड़े गेमप्ले सिस्टम के लिए सबसे अच्छा विकल्प नहीं है क्योंकि कोड को दोहराना और व्यवस्थित करना कठिन होता है, लेकिन छोटे कोड के लिए यह अनुकूल है।

Python Component बनाम Python Code Component

इसे एक साधारण नियम के रूप में उपयोग करें:

इसका उपयोग करें कब
Python Component व्यवहार को पुन: उपयोग, संपादित करना चाहिए, या समय के साथ विकसित होना चाहिए।
Python Code Component व्यवहार छोटा, स्थानीय है।

उदाहरण के लिए, एक पुन: प्रयोज्य EnemyAI को एक Python Script एसेट होना चाहिए जिसका उपयोग Python Component द्वारा किया जाता है। एक छोटे कोड जो कुछ प्रिंट करता है या एक बटन दबाने पर एक फ़ंक्शन कॉल करता है, वह एक Python Code Component हो सकता है।

एक अच्छा पहला स्क्रिप्ट लक्ष्य

Cave स्क्रिप्ट का एक अच्छा पहला लक्ष्य कुछ छोटा और दृश्य है।

इनमें से एक बनाने का प्रयास करें:

  • एक प्लेटफॉर्म जो आगे बढ़ता है।
  • एक दरवाजा जो दृश्य शुरू होने पर खुलता है।
  • एक प्रकाश जो हर कुछ सेकंड में चालू और बंद होता है।
  • एक.pickup जो ध्वनि को चलाता है और खुद को अक्षम करता है।
  • एक बटन जो दूसरे दृश्य में बदलता है।

ये उदाहरण छोटे हैं, लेकिन ये सबसे महत्वपूर्ण कार्यप्रवाह सिखाते हैं: एंटिटी प्राप्त करें, घटक प्राप्त करें, कुछ बदलें, प्ले मोड में परीक्षण करें, और समायोजित करें।

आपको क्या याद रखना चाहिए

Cave में Python स्क्रिप्ट आमतौर पर Python Components के माध्यम से एंटिटीज़ से जुड़ी होती हैं।

सबसे महत्वपूर्ण शुरुआती पैटर्न है:

  1. start() का उपयोग करके संदर्भ प्राप्त करें और मान तैयार करें।
  2. प्रत्येक फ्रेम में कार्रवाई करने के लिए update() का उपयोग करें।
  3. self.entity का उपयोग करके स्क्रिप्ट के मालिक एंटिटी तक पहुंचें।
  4. वस्तु को वास्तव में गति करने, एनिमेट, ध्वनि चलाने, या नियंत्रित करने के लिए घटकों का उपयोग करें।

एक बार जब यह पैटर्न स्वाभाविक लगे, तो Cave में स्क्रिप्टिंग बहुत कम रहस्यमय हो जाती है। आप केवल कोड नहीं लिख रहे हैं। आप एंटिटीज़ को सिखा रहे हैं कि कैसे बर्ताव करना है।