مساحة اعلانية

آخر المواضيع

بناء لعبة كاتربيلر بإستخدام Cocos2D: الحركة والقذائف


هذه هي الحلقة الخامسة من سلسلة دروس عن الـ Cocos2D لإستنساخ لعبة الحشرة إلى iOS (أي-او-إس). قبل أن تبدء في هذا الدرس تأكد من أن تكمل الأجزاء السابقة. 

فى المرة السابقة

فى المرة السابقة تناقشنا فى موضوع AI of the caterpillar وتعلمنا كيف نحرك caterpillar خلال حقل الانبات وحدود المستوى

فى درس اليوم سنقفز فى كل انحاء المكان ونتناقش حول حركة اللاعب و واطلاق الصواريخ

الخطوة الاولى التحكم باللاعب

التحكم باللاعب بسيط وسهل الى حد ما أول شيء يتعين علينا القيام به هو أن تخبر طبقة لعبتنا للتطبيق اللمسات من أجل التفاعل معها.
اضف الكود التالى الى init فى نظام (كود) GameLayer.m:

[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
كما رايتم فى الدرس الاول هذا الكود بساطة سيسمح لgame layer  لان يكون مندووب اللمس لاستلام الاشعارات من اللمسات الان هناك نظامان نحتاج الى تنفيذهما اضف النظامين (الاكواد) الى GameLayer.m


// 1- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {    return YES;}

// 2- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {       
    // 3    CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
    CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];    oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];    oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
    // 4    int xChange = touchLocation.x - oldTouchLocation.x;    int yChange = touchLocation.y - oldTouchLocation.y;
    int newX = self.player.position.x + xChange;    int newY = self.player.position.y + yChange;
    // 5    if(newX < kGameAreaStartX + kGameAreaWidth - kGridCellSize &&        newX > kGameAreaStartX &&       newY > kGameAreaStartY + kGridCellSize / 2 &&       newY < kGameAreaStartY + (kGridCellSize * 3)) {

        __block BOOL collide = NO;        CGPoint oldPosition = self.player.position;                             // 6        self.player.position = ccp(newX,newY);
        // 7        [self.sprouts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {            Sprout *sprout = (Sprout *)obj;            CGRect sproutRect = [sprout getBounds];            CGRect playerRect = [self.player getBounds];
            if(CGRectIntersectsRect(sproutRect, playerRect)) {                collide = YES;                *stop = YES;            }
        }];
        // 8        if(collide) {            self.player.position = oldPosition;        }    }}
فى البداية نحتاج الى تنفيذ ccTouchesBegan حتى نسمح للمتصل بمعرفة اننا نستجيب للمسات. اذا قمت بحذف هذه ستتحطم لعبتك
بعد ذلك طريقة ccTouchesMoved التى يتم استدعائها هندما يمرر اللاعب اصبعه على الهاتف
الحصول على مرجع او اشارة عن احداثى مكان اللمسة الحالية واحداثى مكان اللمسة السابقة
الحصول غلى التغير من احداثى الموقع القديم والجديد سنستخدم هذا التغير لتحديد مدى تحرك اللاعب
هنا لدينا سلسلة من الاختبارات للتأكد من أن اللاعب يبقى داخل "المنطقة اللاعب" أو المربع المحيط الظاهري الذي أنشأنا لهم. و الكود السابع فى الواقع هو الذى يحرك اللاعب
تحديث مكان اللاعب
نحن هنا بصدد التحقق لمعرفة ما إذا كان لاعب يصطدم مع أي من البراعم. براعم تشكل عقبات للاعب، ونحن نريد تقييد حركة اللاعب إذا كانوا في طريقه.
واخيرا اذا كان هناك تصادم يُحول اللاعب الى افضل وضع جيد كان به
الان اذا قمت بتشغيل اللعبة يجب ان تكون قادر على ان تسحب فى اى مكان فى المنطقة الخاصة باللعبة وان تحرك اللاعب فى منطقة ضيقة .

الخطوة الثانية: الكائن الصاروخى

الكائن الصاروخى هو مايسمح لللاعب وعناصر اللعبة الاخرى بالتفاعل اللاعب سيطلق تيار مستمر من الصواريخ بسرعة وفترات زمنية متفاوتة على حسب مستواه

قبل البدا نحتاج الى انشاء بعض الثوابت التى سنحتاج اليها فيما بعد افتح GameConfig.ه وق مباضافة الاسطور التالية

#define kMissileSpeed 1.0#define kMissileMaxSpeed 10.0#define kMissilesTotal 20#define kMissileFrequency .6 //seconds#define kMinMissileFrequency .2
ساقوم بتوضيح لانعا تاتى مع الكود التالى الان انشئ كائن جديد للعبة اسمه الصاروخ اضف الكود التالى الىMissile.h:

#import "cocos2d.h"#import "GameObject.h"
@interface Missile : GameObject@property (nonatomic, assign) BOOL dirty;- (void)update:(ccTime)dt;@end
سيتم استخدام خاصية dirty  للدلالة غلى ان الصاروخ لم يعد باللعبة يمكن ان يكون هذا بسبب الخروج من الشاشة او الاصطدلم بكائن اخر فى اللعبة  منذ ان تتحرك الصواريخ باستمرار ستحتاج الى تحديث لطريقة تحريكهم 

الان قم بفتح Missile.m وقم بنسخ الكود التالى 

#import "Missile.h"#import "GameLayer.h"#import "GameConfig.h"
@implementation Missile
@synthesize dirty = _dirty;
// 1- (id)initWithGameLayer:(GameLayer *)layer {
    if(self == [super initWithGameLayer:layer]) {        self.sprite = [CCSprite spriteWithSpriteFrameName:@"missile.png"];         }
    return self;}
- (void)update:(ccTime)dt {    // 2    int inc = kMissileSpeed * (self.gameLayer.level + 1.5);
    // 3    if(inc > kMissileMaxSpeed) {        inc = kMissileMaxSpeed;    }
    // 4    int y = self.position.y + inc;    self.position = ccp(self.position.x,y);
    // 5    if(self.position.y > kGameAreaStartY + kGameAreaHeight) {        self.dirty = YES;    }}
@end
طريقة اللاinit الخاصة بنا تبدو مالوفة للغاية وهى مسؤلة فقط لانشاء روح الصاروخ
هذه هى السرعة التى سيتحركبها الصاروخ وهويبدا بالقيمة الاساسية ويُسرع استنادا الى المستوى الحالى
عند مرحلة ما قد تخرج سرعة الصاروخ عن السيطرة  نحن نمنع ذلك باضافة اقصى سرعة
هذان السطران هما فى الواقع من يحركان الصاروخ للامام نحن نحسب قيمة جديدة للصاروخ وتحديث الموقع
اخيرا اذا اصطدم الصاروخ بالجزء العلوى نحول خاصية _dirty  الى true سنقوم بجمع القمامة من الصواريخ القذرة داخل 
الخطوة الثالثة اطلاق الصواريخ

الان نحن نمتلك بعض الصواريخ لاطلاقها نحتاج الى اطلاقهم من اللاعب بصفة عامة عندما تمتلك كمية كبيرة من الاجسام مثل الصواريخ انت تريد اعادة استخدام اكبر عددممكن دون تخصيص صواريخ جديدة اثناء تشغيل الحلقة الرئيسية لحل هذه القضية سننشا مصفوفتين مصفوفة ستملك كل الصواريخ احالية داخل اللعبة تم اطلاقهم بواسطة اللاعب والثانية ستملك الصواريخ الباقية للاطلاق فى نهاية طريقة التحديث سننظف كل خاصية dirty من الصواريخ وننقلهم من مصفوفة  "in play" داخل اللعب الى المصفوفة الاخرى "pool"

اضف الكود الخصائص التالية الى ملف 

@property (nonatomic, retain) NSMutableArray *missilesWaiting;@property (nonatomic, retain) NSMutableArray *missilesFiring;
الان افتح GameLayer.m وقم باستيراد ملف Missile.h واضف السطور التالية الى طريقة init الخاصة بك

// 1_missilesWaiting = [[NSMutableArray alloc] initWithCapacity:kMissilesTotal];_missilesFiring = [[NSMutableArray alloc] initWithCapacity:kMissilesTotal];// 2for(int x = 0; x < kMissilesTotal; x++) {    Missile *missile = [[Missile alloc] initWithGameLayer:self];    [self.missilesWaiting addObject:missile];    [missile release];}
تهيئة كلا من المصفوفتين
حلقة kMissilesTotal تنشا كائنات صواريخ عديدة مرة واحدة يتم انشاؤهم ونضيفهم الى مصفوفة 
بعد ذلك القفزالى طريقة التحديث باضافة الكود التالى 


// 1static float missleFireCount = 0;
- (void)update:(ccTime)dt {
    // ...Caterpillar code...
    // 2    float frequency = kMinMissileFrequency;    if(kMissileFrequency / (self.level * 1.25) > kMinMissileFrequency) {        frequency = kMissileFrequency / self.level;    }
    // 3    if(missleFireCount < frequency) {        missleFireCount += dt;    } else {        missleFireCount = 0;        // 4        if([self.missilesWaiting count] > 0) {            Missile *missile = [self.missilesWaiting objectAtIndex:0];            [self.missilesFiring addObject:missile];                    [self.missilesWaiting removeObjectAtIndex:0];                          missile.position = self.player.position;                        [self.spritesBatchNode addChild:missile.sprite];
        }            }
    // 5    __block Missile *dirty = nil;    [self.missilesFiring enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {        Missile *missile = (Missile *)obj;        [missile update:dt];        if(missile.dirty) {            dirty = missile;            *stop = YES;        }    }];
    // 6    if(dirty) {        dirty.dirty = NO;        [self.missilesWaiting addObject:dirty];        [self.missilesFiring removeObject:dirty];        [self.spritesBatchNode removeChild:dirty.sprite cleanup:NO];    }}
نحتاج الى انشاء عداد ثابت للمساعدة فى تسهيل التردد الذى ينطلق منه الصواريخ
حساب تردد اطلاق الصواريخ كما يزداد المستوى يزداد التردد ايضا
نحن نحتاج فقط الى اطلاق صاروخ جديد اذا كان التردد اكبر من او مساويا للتردد المحدد لكل مستوى
سحب الصاروخ من مصفوفة الانتظار (اذا كان بها) واضافتها لمصفوفة الاطلاق فى هذه المرحلة ايضا اضفنا روح الصاروخ لعقدة الدفع التى يمكن استخلاصها
التحقق من تعداد كافة الصواريخ من وجود واحد فذر اذا وجدنا واحد تذكر اى واحد يمكننا تحريكه مجددا الى مصفوفة الانتظار
اذا كان هناك صاروخ قذر نحركه من مصفوفة الانتظار الى مصفوفة الاطلاق وحذف روحه من عقدة الدفع
هذه هى كل الاكواد اللازمة لتحريك الصوارريخ تقدم للامام وقم بتشغيل اللعبة عند هذه النقطة شاهد الصواريخ منطلقة من اللاعب وانت تتحرك حولها .

خاتمة

الان نحن سمحنا للاعب وبعض الصواريخ بالتحرك الان بدات تشعر انها حقا لعبة  كما اننا كشفنا بعض التصادم بين اللاعب و البراعم فى الجزء القادم من السلسلة سندخل اعمق فى كشف الاصطدام بين الصواريخ والبراعم والحشرة  وبين اللاعب والحشرة.

الكــاتــب

    • مشاركة

ليست هناك تعليقات:

جميع الحقوق محفوظة لــ الشبح للمعلوميات 2019 ©