في هذه السلسلة، سنقوم بإنشاء لعبة الأتاري الشهيرة " الدودة"Centipede بإستخدام مُحرك الألعاب الخاص بنظام آي أو إس: كوكوس تو دي cocos2D.
تم إنشاء هذه اللعبة في الأساس لتعمل علي الأتاري، وتم إطلاقها عام 1980 ضمن مجموعة ألعاب التسلية، ومن ذلك الحين، تم تطويرها لتعمل علي كل أنظمة التشغيل التي من الممكن تخيُّلها.
وفي هذه المقالة سوف نُطلق علي اللعبة إسم Caterpiller. " كتربيلر".
رؤية عامة للسلسة التعليمية:
سنقوم بالتركيز في هذه السلسة علي شرح كل الأدوات المتوفرة في مُحرك الألعاب cocos2D والتي توفّر كل الادوات اللازمة لإنشاء لعبة كاملة من البداية إلي النهاية، سنقوم أيضًا بإستخدام بعض الأدوات الأخري مثل Texture Packer لكي يساعدنا طوال العمل.
في نهاية هذه السلسة، سيكون بين يديك نسخة كاملة من لعبة centipede، بكل أجزاءها التقنيّة من الأشكال الرسوميّة ( الجرافيكس )، الحركات البسيطة ( انيميشن)، تفاعل المستخدام مع اللعبة، الذكاء الإصطناعي، منطق اللعبة، والصوتيات.
خلال هذه السلسلة ستتعلم كيف تبني لعبة حقيقة متوفرة علي متجر الآيي تونز، iTunes App Store، لذلك فإن أفضل طريقة لكي تعرف عن ماذا تدور هذه السلسلة أن تقوم بتحميل اللعبة من هنا ( لينك)، وتقوم بتجريبها بنفسك.
تنظيم السلسلة:
هذه السلسلة مُقسمّة إلي سبعة أجزاء منفصلة:
الجزء الأول: سنقوم في هذا الجزء بالتركيز علي إستيراد ملفات العمل، إنشاء مشروع في cocos2D، سأريك كيفية إستخدام Texture Packer لإعداد ملفات العمل بشكل جيد.
الجزء الثاني: سنقوم في هذا الجزء بإنشاء مساحة العمل، يتضمن هذا الجزء تجميع كل عناصر الرسومات Sprites ووضعهم في مكان واحد، سنري أيضًا كيفية رسم وتصميم شكل واجهة اللعبة.
الجزء الثالث: سنقوم بتطوير لعبتنا اﻷساسيّة " كتربيلر Caterpillar" أو الدودة، وسنقوم بتحريها علي الشاشة كلها.
الجزء الرابع: سيكون هذا أكثر الأجزاء تعمقًا، سيكون هذا الجزء عن الذكاء الإصطناعي AI في اللعبة، وكيف يمكن أن تتفاعل مع العالم، قم بالتفكير وأبق ذهنك متقدًا.
الجزء الخامس: في وقت ما، نريد أن نجعل اللعبة قابلة للعب من مستخدم ما، سيركز هذا الجزء علي دعم العلاقة بين اللعبة وبين المستخدم.
الجزء السادس: ستتعلم هنا كيفية الكشف عن التصادمات Collision مع برنامج cocos2D، سنري كيف أن كل كائن يتفاعل معًا لجعل اللعبة تعمل.
الجزء السابع: في ختام هذه السلسلة، لقد قمنا بإلإنتهاء مع وضع صوتيات اللعبة، إحراز النقاط، وحالات إعادة التشغيل.
اولاً: الحصول علي cocos2D
قبل أن تبدأ سوف تحتاج لتحميل وتنصيب كل من مُحرك الألعاب cocos2D ويمكنك الحصول عليه من هنا .http://cocos2d-iphone.org/download.، عندما تكون قد إنتهيت من تحميله وتنصيبه، ستحتاج إلي الحصول علي نماذج برنامج xCode الخاصة بـ cocos2D، ستقوم هذه النماذج بتبسيط العمل كثيرًا في المستقبل إذا كنت ستقوم بإنشاء مشروع جديد بإستخدام cocos2D هذه مقالة تشرح كيفية عمل ذلك ( لينك )، إنّه امر بسيط، فقط قم بتحميل مجموعة النماذج template tarball ثم قم بوضعها في المسار: ~/Library/Developer/Xcode/Templates
علي الجهاز خاصتك، وفي المرة التالية التي تقوم فيها بفتح برنامج xCode يُفترض أن تري مجموعة من النماذج مع العديد من الخيارات المتوفرة من مُحرك الألعاب cocos2D.
ثانيًا: آداة Texure Packer
تعتبر Texure Packer آداة رائعة، حيث تأخذ مجموعة من الرسوميات وتحولها إلي صورة واحدة، وتقوم بإخراج ال plist، وهي التي تخبر cocos2D كيفية إستخدامهم.
جدير بالذكر أن وجود صورة واحدة يوفر في مساحة القرص الصلب، ويوفر في الوقت اللازم للتحميل، والوقت اللازم للمعالجة.
لكي تبدء قم بتحميل تلك الآداة من هنا، يمكنك تحميل النسخة التجريبية واستخدامها اثناء هذه المقالة، لكنني انصح بشدة بشراء هذه الآداة القوية، لأنها تستحق المال المدفوع تمامًا.
إستيراد ملفات العمل إلي برنامج Texure Packer
إبدأ بتحميل هذه المرفقات الخاصة بهذه المقالة، تحتوي كلا من النسخة العاديّة والنسخة فائقة الجودة للصور التي سوف نعمل عليها، تذكر أن الهاتف آيفون ثري جي إس اصبح مجاني الآن، وأنه هناك الكثير من المستخدمين الذين لا يستخدمون الأجهزة التي تعمل بأسلوب عرض Retina، دعنا لا نستثنيهم من قائمة المستخدمين الموجهة إليهم التطبيق.
ولأننا أصبح لدينا نسختين منفصلتين من الصورة، سنحتاج أن نقوم بهذه العملية مرتين مختلفتين، قم بسحب كل الصورة الموجود في ملجد HD ما عدا الصورتين title-hd.png و الصورة game-over-hd.png إلي برنامج texture packer، سوف يتضح لك مؤخرًا لماذا قمنا بإستثناء هذين الملفين.
توريد ملفات العمل من برنامج Texure Packer
سيقوم البرنامج بتهيئة الصور بشكل آلي، وسيقوم بإنشاء صورة واحدة صغيرة قدر الامكان، تذكر أن برنامج cocos2D يتطلب ان تكون ابعاد الصورة image dimentions مساوية لرقم مرفوع لقوي 2 ( رقم اُس 2 ).
الآن تم وضع جميع الصور، قم بالضغط علي زر نشر publish والذي يوجد في الأعلي، قم بتسميّة الناتج caterpillar-hd، تأكد انك قد قمت بمسح الصور من برنامج Texure packer، وقم بتكرار هذه العملية لكل الصور ذات الجودة العادية والموجودة في المجلد sd، ثم قم بتسمية الناتج caterpillar.
الآن يفترض أن تري أربع ملفات هم:
caterpillar-hd.png, caterpillar-hd.plist, caterpillar.png, caterpillar.plist.
ثالثًا : إنشاء مشروع Cocos2D جديد.
قم بفتح برنامج xCode واختر انشاء مشروع جديد، ثم إختر من الجانب cocos2D يجب ان تظهر لك نافذة كهذه:
قم بتسميّة المشروع Caterpillar وسيقوم برنامج xCode بإنهاء كل شئ تحتاجة لبدء اساسيات المشروع.
رابعًا: شكل اللعبة
يستخدم مُحرك الألعاب cocos2D تسيمات سينمائيّة لتنظيم الكائنات الخاصة به، مثل ( مخرج، مشهد،.. إلخ )، المخرج هو المسئول عن تشغيل وملاحظة المشاهد بداخل التطبيق.
قبل أن نذهب بعيدًا، قم بسحب كل الملفات الخاصة بلعبة كتربيلر والتي قمنا بإنشاءها في الاجزاء السابقة من المشروع، بالمثل ايضًا هؤلاء(title.png, title-hd.png, game-over.png, game-over-hd.png)، قم بالتأكيد من وضع علامة علي المربع لنسخ الملفات إلي مجلد المشروع الخاص بك.
إفتراضيًا، سيتم تزويدك بمشهد، وطبقة إفتراضية تسمي طبقة " اهلاً بالعالم HelloWorld Layer"، ولأننا سنقوم بإنشاء المشهد الخاص بنا، لن نحتاج إلي هذه الطبقة، قم بمسح كلاهما عن طريق مسح الملفات ذات الإمتداد .h و .m
قم بإنشاء كلاس جديد بحيث يكون كلاس ممتد ( موَّرث) من الكلاس CCLayer قم بتسميته GameLayer، وقم بلصق هذا الكود بداخله ( بداخل ملف Gamelayer.h)
#import "cocos2d.h" @interface GameLayer : CCLayer { } @property(nonatomic, retain) CCSpriteBatchNode *spritesBatchNode; + (CCScene *) scene; @end
هذا هو نفس المحتوي الذي كان موجود بداخل الملف HelloWorldLayer لكن تم تغيير الإسم إلي GameLayer، ومع إضافة خاصيّة الـ SpriteBatchNode.
في cocos2D، خاصية الـ SpriteBatchNode تسمح لنا بتجميع كل العناصر حتي يتثني ل OpenGL ES بعرضهم خلال مناداة واحدة فقط.
اما عن الـ OpenGL ES فهو اساسًا حالة من حالات الآلة ( جهاز الكمبيوتر) state machine، والتبديّل بين الحالات المختلفة مُكلف للغاية، لذا فيجب أن تكون حريص علي أن تجعل عملية التبديل أقل ما يمكن، يمكنك أن تقوم برسم كل العناصر بإستخدام cocos2D بدون إستخدام CCSpirteBatchNode، برغم ذلك فلا تضمن حين يتم بدء الرسم ألا يؤثر هذا علي الآداء!
دالة المشهد هي ببساطة عبارة عن دالة بداخل كلاس، تقوم بإرجاع نُسخة مفردة من الـ GameSence. سيتم منادة هذه الدالة فقط عندما نُخبر المُخرج The Director ببدء اللعبة، سوف نري تنفيذ هذا الكود في جزء لاحق:
قم بفتح الملف GameLayer.m وقم بإلصاق هذا الكود:
#import "GameLayer.h"
@implementation GameLayer
@synthesize spritesBatchNode = _spritesBatchNode;
+(CCScene *) scene {
CCScene *scene = [CCScene node];
GameLayer *layer = [GameLayer node];
[scene addChild: layer];
return scene;
}
- (void) dealloc {
[_spritesBatchNode release];
[super dealloc];
}
-(id) init {
if( (self=[super init])) {
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA4444];
// 1.
self.spritesBatchNode = [CCSpriteBatchNode batchNodeWithFile:@"caterpillar.png"];
[self addChild:self.spritesBatchNode];
// 2.
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"caterpillar.plist"];
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB565];
// 3.
CCSprite * background = [CCSprite spriteWithSpriteFrameName:@"background.png"];
background.anchorPoint = ccp(0,0);
[self.spritesBatchNode addChild:background];
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_Default];
}
return self;
}
@end
بدايّة من دالة المشهد scence method، سنري الجزء التقليدي من الكود، والذي يقوم ببدء الطبقة الأساسيّة للمشهد، نقوم بمنادة دالة node والتي تقوم بالبدء وإرجاعها مرة أخري الي المُنادي The Caller.
في النهاية، فإن بداية المشهد تم إرجاعها، سوف تري كود مشابه تمامًا لهذا الجزء من الكود في كل مشهد تقوم بإنشاءه.
الدالة init هي كل ما سنقوم بصنعه أثناء عملية إنشاء اللعبة وتحميل مجموعة العناصر الأساسيّة main SpriteSheet إلي الذاكرة.
1- المكان حيث نقوم ببدء كائن object من كلاس CCSpriteBatchNode مع الملف caterpiller.png sheet file، ستقوم أيضًا بالبحث عن ملف بنفس الاسم ولكن بإمتداد .plist لكي تحدد كيف يمكن إستخدام هذا الملف؟
2- بعد أن يتم تحميل الـ spritesheet، سنقوم بتحميل كل العناصر إلي CCSpriteCache، تقوم هذه الخطوة بتحميل كل العناصر إلي الكاش حيث تسهل عملية إعادة إستخدامهم مرات عديدة بدون الحاجة إلي العودة وتحميلهم مرة أخري من القرص الصلب، وانا أرجح هنا بشدة إستخدام الكاش في تحسين الآداء.
3-الآن يمكننا جلب كل العناصر من الكاش بناء علي الأسماء الحقيقة لكل ملف، وهذا بفضل الملف caterpiller.plist والذي يخبر cocos2D بالعلاقات.
في هذه الحالة، نقوم بجلب الخليفة من الكاش ميموري، وسنقوم بوضعها كتابع child للطبقة في الموضع 0,0 ( والذي هو قمة اليسار)، سوف يقوم هذا بعرض خلفيّة اللعبة.
خامسًا: عنوان المشهد
قبل أن نبدأ في لعب لعبتنا، يجب أن نقدم اللعبة إلي المستخدم، لكي نفعل هذا، يجب أن نقوم بإنشاء ملف جديد بحيث أن يكون ملف ممتد ( مُوَّرث) من الكلاس CCLayer وسنقوم بتسميته TitleLayer.
الملف TitleLayer.h عبارة عن ملف بسيط للغاية، قم بلصق هذا الكود:
#import "cocos2d.h" @interface TitleLayer : CCLayer+(CCScene *) scene;@end
الشئ الوحيد الذي قمنا بإضافته هنا كان تعريف دالة المشهد scence method، قم بفتح الملف TitleLayer.m وقم بإضافة الكود الآتي:
#import "TitleLayer.h"#import "GameLayer.h"#import "CCTransition.h" @implementation TitleLayer +(CCScene *) scene { CCScene *scene = [CCScene node]; TitleLayer *layer = [TitleLayer node]; [scene addChild: layer]; return scene;} -(id) init { if( (self=[super init])) { [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB565]; // 1 CCSprite * background = [CCSprite spriteWithFile:@"title.png"]; background.anchorPoint = ccp(0,0); [self addChild:background]; // 2 [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES]; } return self;} - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { // 3 [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:.5 scene:[GameLayer scene] withColor:ccWHITE]]; return YES;} @end
هذا الكود يبدو مشابها للكود الذي في الكلاس GameLayer والذي قمنا بشرحه فيما سبق، لكن هناك بعض الإختلافات سنلخصها في الآتي:
1- يقوم هذا الكود بتحميل صورة خليفة لعنوان الشاشة، وسيقوم بعرضها في طبقة TitleScence الأساسيّة.
2- لكي تقوم أي طبقة في cocos2D بقبول لمس الشاشة، يجب أن تقوم بتفعيلها عن طريق الدالة swallowsTouches. ستقوم هذه الدالة بمنادة بعض الدوال الخاصة بالتعامل مع لمس الشاشة، في حالاتنا هذه سنكون مُهتمين فقط بالدالة ccTouchesBegan.
3- عندما يقوم المستخدم بلمس الشاشة ستقوم هذه الدالة بالعمل، أما بالداخل فإننا سنقوم بإستخدام المخرج The Director لتحريك المشهد من الـ TitleScence إلي الـ GameScence بإستخدام مؤثر التلاشي للتحريك Fade Transition، يمكنك رؤية جميع المؤثرات التي يمكن إستخدامها في التحريك بداخل الملف CCTransition.h.
سادسًا: تشغيل المشروع
إذا حاولت ان تقوم ببناء المشروع وتشغيله عند هذه النقطة، سوف يظهر لك خطأ Error، هذا لأن الكلاس AppDelegate مازال يحاول أن يقوم بتحميل الطبقة أهلاً بالعالم HelloWorldLayer، وهذا هو الملف الذي قمنا بمسحه فيما سبق، لذلك يجب أن نقوم بتعديل الكود ونقوم بإخبار التطبيق أن يفتح بمجرد أن نقوم بتشغيله.
قم بفتح الملف AppDelegate.m ثم قم بتحميل TitleLayer:
#import "TitleLayer.h"
تأكد من انك قد قمت بمسح الإستيراد من الملف HelloWorldLayer، بعد ذلك قم بالإنتقال إلي السطر 113، ثم قم بتغيير HelloWorldLayer Scence إلي TitleLayer Scence.
[[CCDirector sharedDirector] runWithScene: [TitleLayer scene]];
الآن قم ببناء المشروع وتشغيله، يفترض إذا قمت بالخطوات السابقة بشكل صحيح أن تحصل علي شكل مثل هذا
يبدو أن اللعبة لم يتم محاذاتها بشكل صحيح، إنّه شئ سهل للغاية لتصليحه، إفتراضيًا تقوم cocos2D بوضع الخيارات بناء علي طرق العرض التي تضمن محاذاة مناسبة، الآن تم خيارات العرض إلي LandScape Mode.
قم بفتح الملف RootViewController.m، ثم قم بالنظر في الدالة "shouldAutorotateToInterfaceOrientation" قم بتغيير الجملة التي تقوم بالإرجاع return statement إلي هذه الجملة:
return ( UIInterfaceOrientationIsPortrait( interfaceOrientation ) );
سيقوم هذا السطر ببساطة بإخبار cocos2D ومتحكمات العرض بإن تدعم فقط وضع البورترية Portrait Mode، الآن عندما تقوم بضغط تشغيل Run ستجد أنه قد تم تصليح محاذاة اللعبة، وستجد أنها تعمل الآن كما كنت تريد تمامًا.
الخلاصة
ما قمنا بعمله اليوم هو أساسيات العمل لتنفيذ كود لعبة الدودة Centipedo بإستخدام cocos2D، وتعتبر هذه المقدمة هامة للغاية للدروس المتقدمة فيما بعد.
ماذا بعد ؟
في الدروس القادمة من هذه السلسلة، سنقوم ببناء عناصر الواجهة Interface Elements، والتي من بينها:
النقاط المحرزة Score، مرات اللعب المتاحة Lives، حقول اللعب sprout Fields.
ليست هناك تعليقات: