هذا الجزء الثالث من دورة cocos2d لانشاء لعبة الدودة لاجهزة ios فيه درس اليوم سنبدا برمجة الدودة (جسم الحشرة) والحركة تاكد من مراجعة الاجزاء السابقة قبل البدء.
أين توقفنا؟
فى الدرس السابق تعلمنا طريقة انشاء كما تعلمنا ايضا طريقة انشاء العناصر الاساسية لواجهة المستخدم باستخدام cocos2d.
فى درس اليوم سننشا الكائن الاساسى للعبة : الحشرة الحشرة هى اكثر جزء معقد فى
الدورة و سنحتاج الى درسان لشرحها كاملة هذا سيكون الجزء الاول سنبدا انشاء الحشرة مع كل اجزائها ونجعلها تتحرك حول الشاشة فى الجزء الثانى سيكون عن الذكاء الصناعى الذى يقود الحشرة.
الخطوة الأولى: جسم الحشرة.
سيكون جسم الحشرة هو الجزء الاكثر تعقيدا فى دورتنا فانه سيتم اضافة العديد من الخصائص .
بالبداية قم بانشاء ملف من فئة GameObject اسمه caterpiller -اى الحشرة-. انسخ الكود التالى فى ملف Caterpillar.h:
بالبداية قم بانشاء ملف من فئة GameObject اسمه caterpiller -اى الحشرة-. انسخ الكود التالى فى ملف Caterpillar.h:
#import "cocos2d.h"
#import "GameObject.h"@class Segment;// 1typedef enum { CSRight, CSLeft, CSUpLeft, CSUpRight, CSDownLeft, CSDownRight} CaterpillarState;@interface Caterpillar : GameObject// 2@property (nonatomic, retain) NSMutableArray *segments;// 3@property (nonatomic, assign) CaterpillarState currentState;@property (nonatomic, assign) CaterpillarState previousState;// 4@property (nonatomic, assign) ccTime totalTime;@property (nonatomic, assign) NSInteger moveCount;@property (nonatomic, assign) NSInteger level;// 5- (id)initWithGameLayer:(GameLayer *)layer level:(NSInteger)level position:(CGPoint) position;// 6- (void)update:(ccTime)dt;@end
قبل البدا فى شرح الكود اود التحدث عن الهيكل العام للدودة انا اخترت انشائها على ان تكون محدودوة على حالة الدودة هذا يعنى ان سلوك الدودة سيتوقف على حالتها الاحداث فى اللعبة مثل الاصطدامات سيغير حالة الدودة وهذا بد وره يغير سلوكها لذلك يلزمنا معرفة الحالة الحالية للدودة والحالة السابقة لها.
- هذه هى كا الحالات المحتمل حدوثها للدودة يجب ان تكون واضحة نسبيا من اسمائها.
- الدودة عبارة عن صف من القطع كل قطعة تتبع القطعة التى امامها.
- والحالات ستستخدم لتحديد سلوك الدودة
- هنا بعض الخصائص المساعدة التى ستستخدم فى الدرس سنشرح كل واحدة عند استخدامها
- وهذه دالةinit جديدة التى ستاخذ مكان ومستوى داخل حساب اللاعب.
- منذ ان تتحرك الدودة نحتاج الى ربط جميع اجزاء اللعبة دالة التحديث التى سيتم استدعائها من دالة التحديث GameLayer التى سننشاها مؤقتا.
- افتح ملف Caterpillar.m واضف الكود التالى
#import "Caterpillar.h"#import "GameLayer.h"#import "GameConfig.h"@implementation Caterpillar@synthesize segments = _segments;@synthesize currentState = _currentState;@synthesize previousState = _previousState;@synthesize totalTime = _totalTime;@synthesize moveCount = _moveCount;@synthesize level = _level;- (void)dealloc { [_segments release]; [super dealloc];}- (id)initWithGameLayer:(GameLayer *)layer level:(NSInteger)level position:(CGPoint) position { if(self = [super initWithGameLayer:layer]) { self.segments = [NSMutableArray array]; self.level = level; self.currentState = CSRight; self.previousState = CSDownLeft; // 1 [super setPosition:position]; // 2 int length = kCaterpillarLength + self.level / 2;
} return self;}@end
تقريبا لايوجد شئ معقد
- سنكتب دالة setPostion: فى هذا الدرس فيما بعد الان نحتاج الى استدعاء الدالة super حتى لا يتم استدعاء الدالة عن طرسق الامر self.position.
- طول الدودة سيعتمد على المستوى الحالى للاعب كلما زاد مستوى اللاعب يزداد طول الدودة.اضفنا متغير تكوين جديد يسمى kCaterpillarLength اضف هذا الكود الى ملف
#define kCaterpillarLength 11الكود ببساطة يجعل طول الدودة عند البداية 11 قطعة.
الخطوة الثانية : اجسام القطع
كما قلنا من قبل انا الدودة تتكون من صف من القطع لتنفيذه نحتاج الى تعديل دالة الخاصة بالدودة مؤقتا.
أنشئ GameObject باسم القطع Segment. واضف الكود التالى الى
أنشئ GameObject باسم القطع Segment. واضف الكود التالى الى
#import "cocos2d.h"الملاحظة الاساسية عن القطع ان كل قطعة تحتاج الى معرفة القائد اول قطعة ومكانها السابقالقائد هو اول قطعة او الراس فكر فى القطع على انها قائمة مترابطةالان اضف الكود التالى الى
#import "GameObject.h"
@interface Segment : GameObject
@property (nonatomic, assign) CGPoint previousPosition;
@property (nonatomic, assign) Segment *parent;
@end
#import "Segment.h"
#import "GameLayer.h"
@implementation Segment
@synthesize previousPosition = _previousPosition;
@synthesize parent = _parent;
- (id)initWithGameLayer:(GameLayer *)layer {
if(self = [super initWithGameLayer:layer]) {
self.sprite = [CCSprite spriteWithSpriteFrameName:@"segment.png"];
[self.gameLayer.spritesBatchNode addChild:self.sprite];
} return self;
}
- (void) setPosition:(CGPoint)position {
_previousPosition = self.position;
[super setPosition:position];
}
@end
هذه هى دالة initWithGameLayer فلا يوجد شئ جديد الاضافة الوحيدة هى تخطى الدالة لتعقب المكان السابق للقطع منذ تخطى الدالة setPostionنحتاج الى التاكد من استدعاء الدالة حتى تبدا فى التحرك
هذا كل المتعلق بالقطع الان لنعودالى دالة الخاصة بالدودة لاضافة الاكواد لانشاء قطع جديدة.
الخطوة الثالثة : انشاء القطع
هذا كل المتعلق بالقطع الان لنعودالى دالة الخاصة بالدودة لاضافة الاكواد لانشاء قطع جديدة.
الخطوة الثالثة : انشاء القطع
افتح ملفCaterpillar.m واستورد منه ملفSegment.h واضف الكود التالى لدالة initWithGameLayerداخل دالة الرئيسية
for(int i = 0; i < length; i++) {
// 1 Segment *segment = [[[Segment alloc] initWithGameLayer:self.gameLayer] autorelease];
segment.position = position;
[self.segments addObject:segment];
}
__block Segment *parentSegment = [self.segments objectAtIndex:0];
// 2[self.segments enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Segment *segment = (Segment *)obj;
if(![segment isEqual:parentSegment]) {
segment.parent = parentSegment;
}
segment.position = self.position;
segment.previousPosition = self.position;
parentSegment = segment;
}];
- بدانا بانشاء قطع جديدة واضافتها الى صف القطع وانتهينا من دالة length. وتم تحديد مكان القطع مع مكان الدودة .
- كل قطعة يتم عدها والقائد يتبعه القطع وهذا اختبار للتاكد ان القطعة الاولى هى القائد ليس امامها اى قطعة.
.الخطوة الرابعة تهيئة الدودة
رغم ان الللعبة تبدا بدودة واحدة الا انها قد تزداد بلمسة واحدة من الللاعب, هذا يعنى ان GameLayer قادر على دعم عدد لانهائ من اجسام الدود.افتح ملف واضف الخصائص التالية
رغم ان الللعبة تبدا بدودة واحدة الا انها قد تزداد بلمسة واحدة من الللاعب, هذا يعنى ان GameLayer قادر على دعم عدد لانهائ من اجسام الدود.افتح ملف واضف الخصائص التالية
@property (nonatomic, retain) NSMutableArray *caterpillars;
الان افتح ملف واضف له ملف واضف الكود التالى لدالة
_caterpillars = [[NSMutableArray alloc] init];CGPoint startingPosition = ccp(kGameAreaStartX, kGameAreaHeight + kGameAreaStartY - kGridCellSize / 2);Caterpillar *caterpillar = [[[Caterpillar alloc] initWithGameLayer:self level:self.level position:startingPosition] autorelease];[self.caterpillars addObject:caterpillar];هذه لانشاء دودة واحدة عند موضع البداية
الخطوة الخامسة : تحريك الدودة
فى برنامجCocos2D يمكنك ربط جميع اجزاء اللعبة عن طريق جدولة دالة يتم استدعائها بكل لحظة
اضف الكود التالى لدالة init فى ملف GameLayer.m
[self schedule:@selector(update:)];هذا الكود يحعل Cocos2D يستدعى الدالة update:فى كل لحظة داخل اللعبة
الان اننفذ هذه الدالة اضف الكود التالى
- (void)update:(ccTime)dt {
[self.caterpillars enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Caterpillar *caterpillar = (Caterpillar *)obj;
[caterpillar update:dt];
}];}
فى هذا الكود يتم عد كل الدود واستدعاء دالة update الخاصة بهم
الان لنعود لملف Caterpillar.mلاضافة كود دالةupdate:
- (void)update:(ccTime)dt {1. منذ ان جعلنا سرعة الدودة 16 بيكسل فى الللحظة نحتاج الى شيئ اخ لتحديدي سرعتها و الحل فى تحديد السرعة حسب المستوى كلما زاد المستوى زادت سرع الدودة
// 1 self.totalTime += dt;
if(self.totalTime < 4.0 / (self.level * 2.0)) {
self.totalTime += dt;
return;
} else {
self.totalTime = 0;
} // 2 __block int x = self.position.x;
__block int y = self.position.y;
// 3 x += kGridCellSize;
// 4 self.position = ccp(x,y);
}- (void)update:(ccTime)dt {
// 1 self.totalTime += dt;
if(self.totalTime < 4.0 / (self.level * 2.0)) {
self.totalTime += dt;
return;
} else {
self.totalTime = 0;
} // 2 __block int x = self.position.x;
__block int y = self.position.y;
// 3 x += kGridCellSize;
// 4 self.position = ccp(x,y);}
2. نحتاج الى معرفة مكان الدودة الحالى لتعديل هذه المتغيرات
3. هذه الزيادة هي مؤقتة لمجرد إظهار الحركة الأساسية لهذه الدورة سنقوم بتبديلها فى النهاية بشئ اكثر تعقيدا زيادة قيمة المتغير x لتحريك الدودة الى الجانب الايمن من الشاشة
4. اخيرا يتم تغيير موقع الدودة بعد تعديل متغيرات المكان
الخطوة الاخيرة لتحريك الدودة هى تخطى الدالةsetPosition
اضف الكود التالى الىCaterpillar.m:.
- (void) setPosition:(CGPoint)position {
// 1 [super setPosition:position];
// 2 Segment *head = [self.segments objectAtIndex:0];
head.position = position;
// 3 [self.segments enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Segment *segment = (Segment *)obj;
if(segment.parent) {
segment.position = segment.parent.previousPosition;
} }];}
1.الخطوة الاولى هما هى استدعاء الدالة لتحديث كل شئ بصورة صحيحة تبعا للقائد
2. بصفة اساسية تحريك الدودة يعنى تحريك راسها
كل القطع يتبعها بعدها
3. كل القطع يجب ان تتبع المكان السابق للقائد
3. كل القطع يجب ان تتبع المكان السابق للقائد
بعد تشغيل اللعبة يجب ان تتحرك الدودة اعلى الاشة كما بالصورة
الخلاصة.
قمنا بتحريك الدودة داخل حاليا ستلاحظ ان الدودة تتحرك يمينا عندما تصل للحافة وهذا ما سنناقشه المرة القادمة.
قمنا بتحريك الدودة داخل حاليا ستلاحظ ان الدودة تتحرك يمينا عندما تصل للحافة وهذا ما سنناقشه المرة القادمة.
فى الدرس القادم .
سنتعلم كيف تتفاعل الدودة مع البراعم و االحوائط وساشرح لكم كيف تتعدل حالة الدودة وييؤدى الى حدوث رد فعل
ليست هناك تعليقات: