Cocos2D-iphone का उपयोग कर iOS के लिए एक अंतहीन दौड़ खेल विकसित करना

आज मैं आपको उदाहरण के रूप में हाल ही में जारी बी रेसिंग गेम का उपयोग करके Cocos2D पर आधारित एक iOS गेम के निर्माण के बारे में बताना चाहता हूं (Bee Race)।
गेमप्ले में कुछ भी जटिल नहीं है - यह अनिवार्य रूप से एक अंतहीन धावक है जिसमें आपको अंक एकत्र करने और बाधाओं को चकमा देने की आवश्यकता होती है। केवल एक लाल बालों वाली लड़की या एक खजाना शिकारी के बजाय, एक दो-आयामी मधुमक्खी यहां उड़ती है।
रुचि रखने वालों के लिए, मैं कात (अखुटुंग! मिनिन अंड कई पत्र) मांगता हूं।
विचार करने के लिए मुख्य अनुभाग:
  1. Cocos2D का बहुत संक्षिप्त परिचय
  2. हम StoryBoard के साथ एक साथ Cocos2D का उपयोग करते हैं
  3. गेमप्ले और प्रोजेक्ट संरचना का संक्षिप्त विवरण
  4. हम उपकरण खरीदते हैं और क्या करना है अगर एक अजीब किस्में हैं
  5. एप्लिकेशन बिलिंग एप्‍लि‍केशन की तरह गंध नहीं करता है या क्‍या करता है
  6. हम समाजीकरण कर रहे हैं। हम गेम सेंटर से कनेक्ट करते हैं और दो खिलाड़ियों के लिए एक मल्टीप्लेयर संस्करण बनाते हैं
  7. अकेला क्या छूटा
  8. Pablish


स्पॉइलर:




1. Cocos2D का बहुत संक्षिप्त परिचय।

Cocos2d-iphone iOS के लिए एक निशुल्क 2D इंजन है जो हार्डवेयर-त्वरित ग्राफिक्स के लिए OpenGL का उपयोग करता है और भौतिकी इंजन के रूप में Chipmunk या Box2D का समर्थन करता है।
दरअसल, हमें इंजन की आवश्यकता क्यों है? स्प्राइट लोडर (स्प्राइट शीट से विशेष रूप से) लिखने की आवश्यकता से बचने के लिए, एनिमेशन, गेम टाइमर और भौतिकी इंजन को सही ढंग से शुरू / बंद करना। अच्छी तरह से और मुख्य बात हार्डवेयर ग्राफिक्स त्वरण है, यदि आप एक गेम बनाते हैं, तो कोको टच घटकों के आधार पर, सरल ग्राफिक्स के साथ, फिर गेम तत्वों की एनएचटी संख्या के बाद, आप सक्रिय रूप से बुलेट-टाइम प्रभाव जगह से बाहर और जगह से बाहर निकलेंगे, या खेल आमतौर पर बोस में पूजनीय है।
Cocos2D कैश में सभी स्प्राइट्स को स्टोर करता है, एक स्प्राइट के डुप्लिकेट अपेक्षाकृत हल्के होते हैं, क्योंकि स्प्राइट फ़्रेम के लिए एक लिंक संग्रहीत करता है, लेकिन ग्राफ़िक स्वयं नहीं। एक ही समय में, एक OpenGL बफर में एक स्प्राइट का प्रतिपादन अन्य ग्राफिक तत्वों के एक पेड़ में एक कोको तत्व प्रदान करने की तुलना में एक तेज संचालन है।
भौतिक वस्तुओं के लिए - वे सीधे स्प्राइट से संबंधित नहीं हैं, इसलिए, यदि आप एक स्प्राइट चाहते हैं, उदाहरण के लिए, एक फूल, इसी भौतिक बहुभुज को शामिल करने के लिए, आपको स्प्राइटफ्लावर वारिस लिखना होगा। लेकिन अधिक लचीली प्रणाली - एक फूल को न केवल एक, बल्कि कई बहुभुजों को सौंपा जा सकता है, इसके अलावा, आप यह भी चुन सकते हैं कि कौन सा भौतिकी इंजन का उपयोग करना है।
अब जब हमने सभी अकल्पनीय सूक्ष्मताओं का पता लगा लिया है और कोकोस 2 डी के लिए प्रस्तावित परिचय को पढ़ा है, तो आइए कुछ बारीकियों के बारे में जानें।


2. हम StoryBoard के साथ एक साथ Cocos2D का उपयोग करते हैं

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

स्टोरीबोर्ड में सभी विंडो यहां बताई गई हैं, और गेम की मुख्य विंडो में बस बैकग्राउंड के रूप में Cocos2D सीन है, और इसके ऊपर एक HUD है, जो मानक तत्वों के आधार पर भी बनाया गया है।

ध्यान दें कि स्क्रीन कैसा दिखता है - सफेद पृष्ठभूमि Cocos2D है, जो गेम की शुरुआत में आवश्यक ग्राफिक्स लोड करेगा, और जीवन संकेतक, लाइनें, और अधिक - यह बिल्डर इंटरफ़ेस का उपयोग करके किया जाता है।
मैं इस विवरण के साथ पहले से ही बड़े लेख को नहीं बढ़ाऊंगा कि यह कैसे किया जाता है, बस एक लिंक दें जहां से मैंने कोड कॉपी किया था। मुझे github.com/tinytimgames/CCViewController से प्रेरणा मिली


3. गेमप्ले और प्रोजेक्ट संरचना का संक्षिप्त विवरण

गेमप्ले यह है: मधुमक्खी गतिहीन हो जाती है, और सापेक्षता के सिद्धांत के अनुसार, क्षेत्र की ओर बढ़ती है, मकड़ियों और जहरीले पौधों के रूप में विभिन्न खतरों को सहन करती है, साथ ही साथ सिंहपर्णी और सिंहपर्णी बीज के रूप में विभिन्न बन्स। Cocos2D में वास्तव में एक कैमरा ऑब्जेक्ट है जो खिलाड़ी का अनुसरण कर सकता है, लेकिन व्यवहार में यह CCLayer को स्थानांतरित करना आसान हो गया है जिस पर खेल की दुनिया स्थित है।
प्रबंधन सबसे सरल है - स्क्रीन पर टैप करें, मधुमक्खी नीचे उड़ गई, फिर से टैप करें। फिर भी, यह पता चला कि खिलाड़ी सहज रूप से एक स्लाइड बनाना चाहते हैं और इसलिए यह पहली बार में सुविधाजनक नहीं है।
दुनिया की पीढ़ी एक समान नहीं है, लेकिन एक साधारण एल्गोरिथ्म के अनुसार बैचों में है। खेल में वस्तुओं के साथ भरने के लिए तीन विशेष परतें हैं। खेल की शुरुआत में, तीनों वस्तुओं से भरे हुए हैं। फिर परतों में से एक को लिया जाता है और एक निश्चित लंबाई के लिए वस्तुओं से भरा जाता है। कुछ समय बाद, अगला खंड भर जाता है, लेकिन दूसरी परत में, और फिर तीसरा। जब एक मधुमक्खी दूसरे खंड से तीसरे तक उड़ती है, तो पहली परत को साफ किया जाता है, और फिर चौथे खंड को इसमें भरना शुरू हो जाता है और इसी तरह। दो परतों के साथ तिरस्कृत किया जा सकता है, लेकिन तब प्रभाव से निपटना अधिक कठिन होगा जब एक वस्तु जो एक खंड से दूसरे खंड में उड़ती है (मेरे मामले में, ऐसी वस्तुएं केवल सिंहपर्णी बीज उड़ रही हैं)। यह इस तथ्य के कारण है कि वस्तुओं को एक झटके में हटा दिया जाता है, और समन्वय-वार नहीं।
परियोजना भौतिकी इंजन चिपमंक का उपयोग करती है। मैंने इसे दो कारणों से लिया। सबसे पहले, यह सरल प्रतीत होता है, और दूसरी बात, मैंने पहले ही Box2D के साथ निपटा लिया जब मैंने AndEngine का उपयोग किया, लेकिन मैं कुछ नया चाहता था। गेम ऑब्जेक्ट्स के साथ मधुमक्खी की टक्कर का निर्धारण करने के लिए केवल इंजन की आवश्यकता होती है, दुष्ट पक्षियों की तरह कोई भौतिकी नहीं है।


4. हम उपकरण खरीदते हैं और अगर एक अजीब किस्में हैं तो क्या करना है

आकस्मिक खेलों को विकसित करने में मुख्य बात साइकिल में नहीं जाना है। मैं सुरक्षित रूप से कह सकता हूं कि एंग्री बर्ड्स का मुख्य हत्यारा केवल पूर्णतावाद हो सकता है। लेकिन भले ही यह MyObject बेस क्लास के साथ एक सुपर फ्रेमवर्क बनाने के लिए संभव नहीं है , जिसे विशेष रूप से डिज़ाइन किए गए संपादक द्वारा संपादित किया जा सकता है, इसका मतलब यह नहीं है कि कई चीजें स्वचालित नहीं हो सकती हैं।
सबसे पहले, लिनक्स-वे जीवन बहुत सरल है। उदाहरण के लिए, एक कलाकार मुझे ड्रॉपबॉक्स में उच्च रिज़ॉल्यूशन में चित्र बनाता है। मेरे पास एक स्क्रिप्ट है जो उन्हें कम रिज़ॉल्यूशन में परिवर्तित करती है (mogrify, huh) + को –hd वर्जन (@ 2x स्थिति के आधार पर) जोड़ता है।
इंटरफ़ेस बिल्डर के साथ संयोजन में Cocos2D का उपयोग करना भी मुख्य रूप से समय अनुकूलन के बारे में है।
TexturePacker भी बहुत उपयोगी हो सकता है, जो सभी स्प्राइट्स को एक स्प्राइट शीट में पैक कर देगा और इस प्रकार खपत की गई मेमोरी को कम कर देगा, जब तक कि आप पहले से ही सभी स्प्राइट्स को कई दो के आकार में बनाने का प्रबंधन नहीं करते। TexturePacker का भुगतान किया जाता है, लेकिन इसके लायक है। स्प्राइट शीट के साथ, इसमें और भी आसान है कि नया स्प्राइट जोड़ते समय, प्रोजेक्ट में नई फ़ाइलों को जोड़ने की आवश्यकता नहीं है।
2D भौतिकी के लिए मुख्य कठिनाई चित्रों से बहुभुज बनाना है, जो एक भौतिक इंजन द्वारा लोड किया जाएगा। मैन्युअल रूप से ऐसा करना अवास्तविक है, इसलिए आपको किसी प्रकार के उपकरण का उपयोग करने की आवश्यकता है। Inkspace का उपयोग करके एक सदिश संरचना बनाने जैसे कई सुझाव हैं, लेकिन मैंने व्यक्तिगत रूप से इसके लिए AndengineVertexHelper उपयोगिता कोड.google.com/p/andengine-vertex-helper/downloads/list लिखा
इसमें लगभग एक दिन लगा, लेकिन यह बात बहुत उपयोगी साबित हुई। डिफ़ॉल्ट रूप से, कार्यक्रम में एंडेंगी इंजन की कोड पीढ़ी के लिए एक टेम्पलेट है, विवरण यहां दिए गए हैं www.andengine.org/forums/features/vertex-helper-t1370.html
करने के लिए टेम्पलेट बदलें
<real>%.5f</real><real>%.5f</real> 
और plist में स्वरूपण प्राप्त करें।

अगला, वस्तुओं के विवरण के साथ एक फ़ाइल बनाएं:
उदाहरण का विस्तार करें
 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>bee0</key> <dict> <key>vertices</key> <array> <real>-0.41786</real><real>-0.14844</real> <real>-0.40714</real><real>0.07031</real> <real>-0.03929</real><real>0.14453</real> <real>0.27143</real><real>0.15625</real> <real>0.46071</real><real>-0.02344</real> <real>0.45714</real><real>-0.29688</real> <real>0.26786</real><real>-0.46484</real> <real>0.02143</real><real>-0.46094</real> <real>-0.29643</real><real>-0.31250</real> </array> </dict> 


और ऑब्जेक्ट लोडर:
उदाहरण का विस्तार करें
 - (void)createBodyAtLocation:(CGPoint)location{ float mass = 1.0; body = cpBodyNew(mass, cpMomentForBox(mass, self.sprite.contentSize.width*self.sprite.scale, self.sprite.contentSize.height*self.sprite.scale)); body->p = location; body->data = self; cpSpaceAddBody(space, body); NSString *path =[[NSBundle mainBundle] pathForResource:@"obj _descriptions" ofType:@"plist"]; // <- load plist NSDictionary *objConfigs = [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease]; NSArray *vertices = [[objConfigs objectForKey:namePrefix] objectForKey:@"vertices"]; shape = [ChipmunkUtil polyShapeWithVertArray:vertices withBody:body width:self.sprite.contentSize.width height:self.sprite.contentSize.height]; shape->e = 0.7; shape->u = 1.0; shape->data = self; shape->collision_type = OBJ_COLLISION_TYPE; cpSpaceAddShape(space, shape); } 

स्प्राइट्स के पत्राचार और उनके भौतिक अभ्यावेदन का नेत्रहीन परीक्षण करने के लिए, मैं इस चीज़ का उपयोग करने की अत्यधिक सलाह देता हूं: github.com/nubbel/CPDebugLayer
यह बहुत साफ दिखेगा:

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


5. एप्लिकेशन को इन-ऐप बिलिंग की तरह गंध या कनेक्ट नहीं होता है

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


6. हम समाजीकरण कर रहे हैं। हम GameCenter को कनेक्ट करते हैं और दो खिलाड़ियों के लिए एक मल्टीप्लेयर संस्करण बनाते हैं

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


7. क्या याद किया अकेला

विकास के परिणामस्वरूप, कुछ समस्याएं सामने आईं:
1. उपरोक्त नियंत्रण समस्या - इस खेल में नल सहज नहीं है

2. ग्राफिक्स साझा परत के प्रत्येक पुनः आरंभ में थोड़ा रुक जाता है।
इसके अलावा, अगर एक्शन रिपीट होता है जैसे रिपीटफॉरवर, तो व्यावहारिक रूप से ऐसी कोई समस्या नहीं है:
उदाहरण का विस्तार करें
 -(void) infiniteMove{ id actionBy = [CCMoveBy actionWithDuration: BUFFER_DURATION position: ccp(-BUFFER_LENGTH, 0)]; id actionCallFunc = [CCCallFunc actionWithTarget:self selector:@selector(requestFillingNextBuffer)]; id actionSequence = [CCSequence actions: actionBy, actionCallFunc, nil]; id repeateForever = [CCRepeatForever actionWithAction:actionSequence]; [self.bufferContainer runAction:repeateForever]; } 

लेकिन मैंने आंदोलन को धीरे-धीरे तेज कर दिया, इसलिए प्रत्येक क्रिया एक नई कार्रवाई बनाती है। यह ग्राफिक्स को थोड़ा हकलाने का कारण बनता है:
उदाहरण का विस्तार करें
 -(void) infiniteMoveWithAccel{ float duration = BUFFER_DURATION-BUFFER_ACCEL*self.lastBufferNumber; duration = max(duration, MIN_BUFFER_DURATION); id actionBy = [CCMoveBy actionWithDuration: duration position: ccp(-BUFFER_LENGTH, 0)]; id restartMove = [CCCallFunc actionWithTarget:self selector:@selector(infiniteMoveWithAccel)]; id fillBuffer = [CCCallFunc actionWithTarget:self selector:@selector(requestFillingNextBuffer)]; id actionSequence = [CCSequence actions: actionBy, restartMove, fillBuffer, nil]; [self.bufferContainer runAction:actionSequence]; } 

अन्य मामलों में, जब मैंने "बिल्लियों पर" परीक्षण किया, तो किसी भी विषय ने इसके बारे में शिकायत नहीं की, लेकिन यदि आप बारीकी से देखते हैं, तो आप देख सकते हैं।

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


8. और अंत में, प्रकाशन।

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

मुझे उम्मीद है कि यह पढ़ना दिलचस्प था और कोई अपने लिए उपयोगी चीजें लेकर आया था।

Source: https://habr.com/ru/post/In165601/


All Articles