بناء امر قذيفة باستخدام Sprite Kit: بدء تشغيل المشروع 1 |
في هذا الدرس, ستتعلم كيفية استخدام اطار عمل Sprite Kit التابع لـ Apple لاعادة انشاء لعبة امر القذيفة للـ iPad. خلال هذه الفترة, ستتعلم اكثر عن مفاهيم اساسية عديدة مثل العفاريت, اللمسات, الفيزياء, الاصطدامات, و الانفجارات. يهدف هذا الدرس لتويع خبرة اللعبة من خلال اضافة وضع لاعب متعدد.
الذاكرات
هل تتذكر امر القذيفة؟ اصدرت اتاري اللعبة الاصلية في 8 اذار, 1981. كانت لعبة حماسية بنيت لانظمة Arcade و اصبحت مشهورة حول العالم.
منذ اطلاقها عام 1981, تم تطبيق عدة تعديلات من اجل منصات متنوعة. حان الوقت الان لاعادة انشاء اللعبة الاصلية باستخدام التقنيات الحديثة, iOS, Objective-C, و iPad.
ما زال يامكانك لعب اللعبة الاصلية. الق نظرة على IGN و عش مرة اخرى ذكريات الطفولة.
نظرة عامة نهائية
تعطيك الصورة التي في الاسفل فكرة عما ستبدو عليه النتيجة النهائية. اذا اعجبك ما تراه, دعونا نبدأ.
المتطلبات
لتكمل هذا الدرس, ستحتاج الى Xcode 5 و اخر نسخة من iOS 7 SDK. يمكنك تحميل Xcode 5 و SDK من مركز iOS Dev.
في نهاية هذا الجزء, ستجد تحد واحد او اكثر. تعدف هذه التحديات لمساعدتك بالتقنيات المستخدمة في هذا الدرس. يعد بعضهم سهل بينما سيشكل الاخرين تحديا اكبر, حيث سيتطلب فهما اوسع لاطار عمل Sprite Kit. باستثناء اخر تحد, تذكر ان هذه التحديات غير مطلوبة لانهاء الدرس. و لكن نأمل ان تجربهم.
اذا كانت لديك اية اسئلة حول اطار عمل Sprite Kit, نقترح ان تأخذ نظرة على دروس Sprite Kit على Mobiletuts+.
1. بدء المشروع
اطلق Xcode 5 و انشئ Sprite Kit الجديد من خلال اختيار جديد < مشروع... من قائمة الملفات. اختر عارض لعبة SpriteKit, سم مشروعك امر القذيفة, و اختر iPad من قائمة الادوات.
اذا كانت لديك اية اسئلة عن هذه الخطوة, نشجعك على قراءة شرح مفصل اكثر عن هذه الخطوة في بناء لعبة طائرات مع Sprite Kit- بدء تشغيل المشروع.
مع بدء تشغيل المشروع, اضف موارد المشروع, التي يمكنك تحميلها باستخدام الرابط في اعلى الصفحة. سنبدأ بالتركيز على صنف MyScene. داخل MyScene.m, ستجد طريقتين, initWithSize: و touchesBegan:withEvent:.
في initWithSize:, ازل او علق خارج الكود المرتبط بنموذج SKLabelNode بما اننا لا نحتاجه في هذا الدرس. الق نظرة على الانشاء المحدث من initWithSize: اسفلا.
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
}
return self;
}
في touchesBegan:withEvent:, سنقوم بشيء مماثل. حاليا, يجب ان تحوي الطريقة على منطق كشف اللمس و موقع لمسة المستخدم. ستعطيك هذه التغييرات تحذير مجمع, و لكننا سنتخلص من ذلك لاحقا.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
}
}
تقضي الخطوة التالية بانشاء صنفين. سيستخدم الصنف الاول, MenuScene, للقائمة الرئيسية و الصنف الثاني, MultiScene, لواجهة تطبيق اللاعب المتعدد. يعتبر كلا الصنفين اصناف فرعية عن SKScene. سيستخدم صنف MyScene لانشاء واجهة تطبيق اللاعب المنفرد.
كما رأينا في صنف MyScene, فاننا نحتاج الى initializer لكل صنف. حاليا, سيقوم initializer فقط بتعيين لون خلفية المشهد كما رأينا في MyScene.m. يحتاج initializer التابع لصنف MenuScene ايضا لتعيين عنوان اللعبة. لفعل ذلك, يجب ان نهتم ببعض الامور اولا.
- انشئ كائن SKSpriteNode
- عين zPosition التابع له
- عين مقياسه
- عين موقعه
- اضف الكائن كطفل في الصنف
الق نظرة على انشاء initWithSize: من صنف MenuScene من اجل التوضيح.
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
self.backgroundColor = [SKColor colorWithRed:(198.0/255.0) green:(220.0/255.0) blue:(54.0/255.0) alpha:1.0];
SKSpriteNode *title = [SKSpriteNode spriteNodeWithImageNamed:@"title"];
title.zPosition = 2;
title.scale = 0.4;
title.position = CGPointMake(size.width/2,size.height/2);
[self addChild:title];
}
return self;
}
يجب ان يكون لديك الان القائمة الرئيسية و العنوان. حان الوقت لتحديث متحكم المشهد الرئيسي ليتم عرض القائمة كل مرة يتم فيها اطلاق التطبيق. افتح ViewController.m, عين موقع طريقة viewDidLoad, و استبدل نموذج SKScene بنموذج صنف MenuScene كما هو موضح اسفلا.
- (void)viewDidLoad {
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;
// Create and configure the scene.
SKScene * scene = [MenuScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
}
لا تنس استيراد ملف الراس من صنف MenuScene..
#import "ViewController.h"
#import "MenuScene.h"
عظيم. حان الوقت لبناء مشروعك و تشغيله للتحقق فيما اذا كان كل شيء يعمل بالشكل الصحيح. يجب ان ترى واجهة تطبيق مشابهة لتلك التي في الصور اسفلا.
التحدي: لانشاء خبرة فريدة من نوعها, نتحداك ان تقوم بالتالي.
- تعديل الوان خلفية كل مشهد
- اللعب بخصائص كائن عنوان MenuScene
2. الكائنات, الزهور, الوحوش و القذائف
قبل اضافة الكائنات للعبة, نحتاج الى اضافة القدرة على الملاحة في اللعبة. اعلن عن النموذجين UIButton في صنف MenuScene و المتغير, sizeGlobal, من نوع CGSize لتخزن حجم الشاشة. سيساعدنا اللاحق بتحديد موقع الكائنات على الشاشة. قم بتحديث MenuScene.m كما هو موضح اسفلا.
#import "MenuScene.h"
@interface MenuScene () {
CGSize sizeGlobal;
UIButton *singlePlayerButton;
UIButton *multiPlayerButton;
}
@end
عين sizeGlobal للحجم في initializerالصنف كما هو موضح في مقطع الكود اسفلا.
- (id)initWithSize:(CGSize)size {
self = [super initWithSize:size];
if (self) {
self.backgroundColor = [SKColor colorWithRed:(198.0/255.0) green:(220.0/255.0) blue:(54.0/255.0) alpha:1.0];
SKSpriteNode *title = [SKSpriteNode spriteNodeWithImageNamed:@"title"];
title.zPosition = 2;
title.scale = 0.4;
title.position = CGPointMake(size.width/2,size.height/2);
[self addChild:title];
sizeGlobal = size;
}
return self;
}
تاليا, اعلن عن ثلاثة طرق في صنف MenuScene.
didMoveToView: لعرض الازرار عندما تنتقل اللعبة لمشهد القائمة.
moveToSinglePlayerGame التي تنقل اللعبة الى مشهد MyScene و تزيل الازرار.
moveToMultiPlayerGame التي تنقل اللعبة الى مشهد MultiScene و نزيل الازرار ايضا.
في didMoveToView:, يتحقق التطبيق فيما اذا نقل المشهد قد حصل بدون مشاكل, اذا حدث شيء ما, سيقوم التطبيق بتحميل الموارد, و عرضهم للمستخدم, و بدء الازرار.
- (void)didMoveToView:(SKView *)view {
UIImage *buttonImageNormal = [UIImage imageNamed:@"singleBtn.png"];
singlePlayerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
singlePlayerButton.frame = CGRectMake(sizeGlobal.height/8, sizeGlobal.width/2+250, buttonImageNormal.size.width, buttonImageNormal.size.height);
singlePlayerButton.backgroundColor = [UIColor clearColor];
[singlePlayerButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[singlePlayerButton setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
[singlePlayerButton addTarget:self action:@selector(moveToSinglePlayerGame) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:singlePlayerButton];
UIImage *buttonImageNormal2 = [UIImage imageNamed:@"multiBtn.png"];
multiPlayerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
multiPlayerButton.frame = CGRectMake(sizeGlobal.height/2+100, sizeGlobal.width/2+250, buttonImageNormal2.size.width, buttonImageNormal2.size.height);
multiPlayerButton.backgroundColor = [UIColor clearColor];
[multiPlayerButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
UIImage *strechableButtonImageNormal2 = [buttonImageNormal2 stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[multiPlayerButton setBackgroundImage:strechableButtonImageNormal2 forState:UIControlStateNormal];
[multiPlayerButton addTarget:self action:@selector(moveToMultiPlayerGame) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:multiPlayerButton];
}
في didMoveToView:, سنستدعي moveToSinglePlayerGame و moveToMultiPlayerGame. دعونا نقوم بانشاء هذه الطرق تاليا. في كل طريقة, نحتاج الى اضافة التالي:
انشاء نموذج اما MyScene او MultiScene.
انشاء نقل مشهد .
عرض مشهد جديد.
ازالة الازرار.
هل يمكنك انشاء هذه الطرق بمفردك؟ اذا لم تمكن واثقا, الق نظرة على هذا الانشاء اسفلا.
- (void)moveToSinglePlayerGame {
SKScene * scene = [MyScene sceneWithSize:self.view.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
SKTransition* transition = [SKTransition revealWithDirection:SKTransitionDirectionLeft duration:1];
SKView * skView = (SKView *)self.view;
[skView presentScene:scene transition:transition];
[singlePlayerButton removeFromSuperview];
[multiPlayerButton removeFromSuperview];
}
- (void)moveToMultiPlayerGame {
SKScene * scene = [MultiScene sceneWithSize:self.view.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
SKTransition* transition = [SKTransition revealWithDirection:SKTransitionDirectionLeft duration:1];
SKView * skView = (SKView *)self.view;
[skView presentScene:scene transition:transition];
[singlePlayerButton removeFromSuperview];
[multiPlayerButton removeFromSuperview];
}
لا تنس اضافة التصريح المستورد لملف الراس من MyScene و MultiScene.
#import "MenuScene.h"
#import "MyScene.h"
#import "MultiScene.h"
@interface MenuScene () {
CGSize sizeGlobal;
UIButton *singlePlayerButton;
UIButton *multiPlayerButton;
}
@end
قم ببناء و تشغيل التطبيق في محفز iOS او على جهتز فيزيائي. يجب ان تبدو اللعبة الان كالصورة اسفلا.
لقد انهينا القائمة الرئيسية. حان الوقت الان للتركيز واجهة تطبيق اللعب المنفرد (MyScene). سيحتوي الصنف MyScene على معظم منطق اللعبة. تقضي الخطوة الاولى بتحديد موقع الأزهار التي سترمي الرصاصات في اسفل الشاشة. سننشئ ثلاثة ازهار, كل واحدة منهم سيكون لديها خصائصها المميزة.
ستتابع ايضا عددا من القذائف المتفجرة و تعرض تلك القيمة في SKLabelNode اخر تسمى labelMissilesExploded. كما يمكنك ان ترى اسفلا, سنحتاج عددا من متغيرات النماذج او ivars. يهدف كل ivar الى ان يصبح واضحا عندما نحدث طريقة initWithSize: في MyScene.
#import "MyScene.h"
@interface MyScene () {
CGSize sizeGlobal;
SKLabelNode *labelflowerBullets1;
SKLabelNode *labelflowerBullets2;
SKLabelNode *labelflowerBullets3;
SKLabelNode *labelMissilesExploded;
int position;
int monstersDead;
int missileExploded;
int flowerBullets1;
int flowerBullets2;
int flowerBullets3;
}
@end
في initWithSize:, سنقوم بتركيب نماذج SKLabelNode المتنوعة.
- (id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor colorWithRed:(198.0/255.0) green:(220.0/255.0) blue:(54.0/255.0) alpha:1.0];
position = size.width/3;
sizeGlobal = size;
[self addFlowerCommand];
//Label Informing Missiles Exploded
labelMissilesExploded = [SKLabelNode labelNodeWithFontNamed:@"Hiragino-Kaku-Gothic-ProN"];
labelMissilesExploded.text = [NSString stringWithFormat:@"Missiles Exploded: %d",missileExploded];
labelMissilesExploded.fontSize = 30;
labelMissilesExploded.position = CGPointMake(size.width/2,size.height-labelMissilesExploded.frame.size.height);
labelMissilesExploded.zPosition = 3;
[self addChild:labelMissilesExploded];
flowerBullets1 = 10;
flowerBullets2 = 10;
flowerBullets3 = 10;
labelflowerBullets1 = [SKLabelNode labelNodeWithFontNamed:@"Hiragino-Kaku-Gothic-ProN"];
labelflowerBullets1.text = [NSString stringWithFormat:@"%d",flowerBullets1];
labelflowerBullets1.fontSize = 30;
labelflowerBullets1.position = CGPointMake(position-position/2,labelflowerBullets1.frame.size.height/2);
labelflowerBullets1.zPosition = 3;
[self addChild:labelflowerBullets1];
labelflowerBullets2 = [SKLabelNode labelNodeWithFontNamed:@"Hiragino-Kaku-Gothic-ProN"];
labelflowerBullets2.text = [NSString stringWithFormat:@"%d",flowerBullets2];
labelflowerBullets2.fontSize = 30;
labelflowerBullets2.position = CGPointMake(position*2-position/2,labelflowerBullets2.frame.size.height/2);
labelflowerBullets2.zPosition = 3;
[self addChild:labelflowerBullets2];
labelflowerBullets3 = [SKLabelNode labelNodeWithFontNamed:@"Hiragino-Kaku-Gothic-ProN"];
labelflowerBullets3.text = [NSString stringWithFormat:@"%d",flowerBullets3];
labelflowerBullets3.fontSize = 30;
labelflowerBullets3.position = CGPointMake(position*3-position/2,labelflowerBullets3.frame.size.height/2);
labelflowerBullets3.zPosition = 3;
[self addChild:labelflowerBullets3];
}
return self;
}
في initWithSize:, سنقوم ايضا باستدعاء addFlowerCommand, التي لم نغطيها بعد. لا يعد الانشاء صعبا كما يمكنك ان ترى اسفلا. في addFlowerCommand, سنحول الى نماذج ثلاثة من نماذج SKSpriteNode, واحدة لكل زهرة, و نحدد موقعهم في اسفل الشاشة مع مساعدة الموقع.
- (void)addFlowerCommand {
for (int i = 1; i <= 3; i++) {
SKSpriteNode *flower = [SKSpriteNode spriteNodeWithImageNamed:@"flower.png"];
flower.zPosition = 2;
flower.position = CGPointMake(position * i - position / 2, flower.size.height / 2);
[self addChild:flower];
}
}
يمكنك الان بناء و ادارة المشروع في محفز iOS لترى واجهة تطبيق اللاعب المنفرد.
لدينا الازهار الان, و لكن مازلنا بحاجة الى بعض الوحوش. حان الوقت لانشاء طريقة addMonstersBetweenSpace:. في هذه الطريقة, سنقوم بانشاء ثلاثة وحوش و نعين موقعهم بين الازهار . يعد تحديد موقع الوحوش رهننا بمتغير spaceOrder. سنعين موقع الوحوش بشكل عشوائي باستخدام getRandomNumberBetween:to:, الذي يولد عددا عشوائيا بين الارقام المعطية.
- (void)addMonstersBetweenSpace:(int)spaceOrder {
for (int i = 0; i< 3; i++) {
int giveDistanceToMonsters = 60 * i -60;
int randomMonster = [self getRandomNumberBetween:0 to:1];
SKSpriteNode *monster;
if (randomMonster == 0) {
monster = [SKSpriteNode spriteNodeWithImageNamed:@"protectCreature4"];
} else {
monster = [SKSpriteNode spriteNodeWithImageNamed:@"protectCreature2"];
}
monster.zPosition = 2;
monster.position = CGPointMake(position * spaceOrder - giveDistanceToMonsters, monster.size.height / 2);
[self addChild:monster];
}
}
The implementation of getRandomNumberBetween:to: is shown below.
- (int)getRandomNumberBetween:(int)from to:(int)to {
return (int)from + arc4random() % (to - from + 1);
}
نقوم باستدعاء addMonstersBetweenSpace: مرتين في طريقة initWithSize: من صنف MyScene.
- (id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor colorWithRed:(198.0/255.0) green:(220.0/255.0) blue:(54.0/255.0) alpha:1.0];
// ... //
// Add Monsters
[self addMonstersBetweenSpace:1];
[self addMonstersBetweenSpace:2];
}
return self;
}
الان و قد حصلت على الازهار و الوحوش, حان الوقت لاضافة القذائف. سنحتاج الى اتباع الخطوات التالية.
- انشاء SKAction لاستدعاء طريقة.
- انشاء SKAction لاعادة ذلك النشاط.
انشئ addMissilesFromSky:, الذي سيولد عشوائيا ثلاثة قذائف جديدة و اضفهم الى المشهد.
سنعلن عن نماذج SKAction في initWithSize:. الق نظرة على الانشاء المحدث initWithSize: اسفلا.
- (id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.backgroundColor = [SKColor colorWithRed:(198.0/255.0) green:(220.0/255.0) blue:(54.0/255.0) alpha:1.0];
// ... //
// Create Actions
SKAction *wait = [SKAction waitForDuration:2];
SKAction *createMissiles = [SKAction runBlock:^{
[self addMissilesFromSky:size];
}];
SKAction *updateMissiles = [SKAction sequence:@[wait, createMissiles]];
[self runAction:[SKAction repeatActionForever:updateMissiles]];
}
return self;
}
انشاء addMissilesFromSky: موضح اسفلا.
- (void)addMissilesFromSky:(CGSize)size {
int numberMissiles = [self getRandomNumberBetween:0 to:3];
for (int i = 0; i < numberMissiles; i++) {
SKSpriteNode *missile;
missile = [SKSpriteNode spriteNodeWithImageNamed:@"enemyMissile"];
missile.scale = 0.6;
missile.zPosition = 1;
int startPoint = [self getRandomNumberBetween:0 to:size.width];
missile.position = CGPointMake(startPoint, size.height);
int endPoint = [self getRandomNumberBetween:0 to:size.width];
SKAction *move =[SKAction moveTo:CGPointMake(endPoint, 0) duration:15];
SKAction *remove = [SKAction removeFromParent];
[missile runAction:[SKAction sequence:@[move,remove]]];
[self addChild:missile];
}
}
اذا قمت بانشاء و تشغيل التطبيق, يجب ان تبدو النتيجة مشابهة للصورة اسفلا.
التحدي: هذا عظيم, و لكننا نحتاج الى مزيد من الوحوش. نتحداك الى تقوم بالتالي.
اضف وحوش اكثر.
اضف ازهار اكثر.
قم بتعديل حركة القذائف.
3. تفاعل المستخدم
يمكنك رؤية بعض الحركة, و لكننا نحتاج الى التكوينات الاساسية للعبة, تفاعل المستخدم. سنضيف تفاعل المستخدم من خلال فعالية طريقتين, touchesBegan:withEvent: و positionOfWhichFlowerShouldBegin:. لاضافة تفاعل المستخدم يجب علينا ان نأخذ التالي بعين الاعتبار.
كل زهرة يمكن ان يطلق عشرة رصاصات.
يجب عليك ان تكشف موقع لمسة المستخدم و تستخدم اقرب زهرة لاطلاق الرصاصة.
يجب ان تحرك الرصاصة الى موقع لمسة المستخدم.
يجب ان تنفجر عند موقع لمسة المستخدم.
الانشاء المحدث touchesBegan:withEvent: موضح اسفلا.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
// Return if User Taps Below a Flower
if (location.y < 120) return;
int bulletBeginning = 0;
if (location.x >= 0 && location.x < position) {
bulletBeginning = position-position/2;
if (flowerBullets1 > 0)
flowerBullets1--;
else{
if(flowerBullets1 == 0 && flowerBullets2 > 0){
flowerBullets2--;
[labelflowerBullets2 setText:[NSString stringWithFormat:@"%d",flowerBullets2]];
bulletBeginning = [self positionOfWhichFlowerShouldBegin:2];
}
else if(flowerBullets3 > 0){
flowerBullets3--;
[labelflowerBullets3 setText:[NSString stringWithFormat:@"%d",flowerBullets3]];
bulletBeginning =[self positionOfWhichFlowerShouldBegin:3];
}
else{
return;
}
}
[labelflowerBullets1 setText:[NSString stringWithFormat:@"%d",flowerBullets1]];
}
else if((location.x >= position && location.x < position*2)){
bulletBeginning = position*2-position/2;
if(flowerBullets2 > 0)
flowerBullets2--;
else{
if(location.x < sizeGlobal.width/2){
if(flowerBullets1 > 0){
flowerBullets1--;
[labelflowerBullets1 setText:[NSString stringWithFormat:@"%d",flowerBullets1]];
bulletBeginning =[self positionOfWhichFlowerShouldBegin:1];
}
else if (flowerBullets3 > 0){
flowerBullets3--;
[labelflowerBullets3 setText:[NSString stringWithFormat:@"%d",flowerBullets3]];
bulletBeginning =[self positionOfWhichFlowerShouldBegin:3];
}
else{
return;
}
}
else{
if(flowerBullets3 > 0){
flowerBullets3--;
[labelflowerBullets3 setText:[NSString stringWithFormat:@"%d",flowerBullets3]];
bulletBeginning =[self positionOfWhichFlowerShouldBegin:3];
}
else if (flowerBullets1 > 0){
flowerBullets1--;
[labelflowerBullets1 setText:[NSString stringWithFormat:@"%d",flowerBullets1]];
bulletBeginning =[self positionOfWhichFlowerShouldBegin:1];
}
else{
return;
}
}
}
[labelflowerBullets2 setText:[NSString stringWithFormat:@"%d",flowerBullets2]];
}
else{
bulletBeginning = position*3-position/2;
if(flowerBullets3 > 0)
flowerBullets3--;
else{
if(flowerBullets3 == 0 && flowerBullets2 > 0){
flowerBullets2--;
[labelflowerBullets2 setText:[NSString stringWithFormat:@"%d",flowerBullets2]];
bulletBeginning =[self positionOfWhichFlowerShouldBegin:2];
}
else if(flowerBullets1 > 0){
flowerBullets1--;
[labelflowerBullets1 setText:[NSString stringWithFormat:@"%d",flowerBullets1]];
bulletBeginning =[self positionOfWhichFlowerShouldBegin:1];
}
else{
return;
}
}
[labelflowerBullets3 setText:[NSString stringWithFormat:@"%d",flowerBullets3]];
}
}
}
مع الكود طويلة جدا, فانها ليست بذلك التعقيد. افحص فيما اذا تبقى اية رصاصات لكل زهرة و اكشف المنطقة التي نقرها المستخدم من خلال استدعاء positionOfWhichFlowerShouldBegin:, التي سنناقشها خلال لحظة.
if (location.y < 120) return;
تعود طريقة positionOfWhichFlowerShouldBegin: بالموقع الذي يتوافق مع المنطقة الخاصة التي نقر عليها المستخدم. تذكر انك قمت بتقسيم الشاشة الى ثلاثة اجزاء لذا ستحتاج الى كشف المنطقة التي نقر غليها المستخدم و ربطها باحدى الازهار. هذا ما سيبدو عليه الانشاء.
- (int)positionOfWhichFlowerShouldBegin:(int)number {
return position * number - position / 2;
}
لجعل الرصاصات تتحرك, نحتاج الى انشاء نموذج SKSpriteNode اخر. لدى كل رصاصة فترة و SKAction مرتبطة بها. هذا المنطق يوجد ايضا في touchesBegan:withEvent:. الق نظرة على الانشاء المحدث اسفلا.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
// ... //
SKSpriteNode *bullet = [SKSpriteNode spriteNodeWithImageNamed:@"flowerBullet"];
bullet.zPosition = 1;
bullet.scale = 0.6;
bullet.position = CGPointMake(bulletBeginning,110);
bullet.color = [SKColor redColor];
bullet.colorBlendFactor = 0.5;
float duration = (2 * location.y)/sizeGlobal.width;
SKAction *move =[SKAction moveTo:CGPointMake(location.x,location.y) duration:duration];
SKAction *remove = [SKAction removeFromParent];
[bullet runAction:[SKAction sequence:@[move,remove]]];
[self addChild:bullet];
}
}
التحدي: هل انت مستعد لتحد اخر؟ الق نظرة على هذه التحديات.
انشئ و عرف حركات الرصاصة المختلفة.
عدل فترة حركة كل رصاصة
النهاية
اذا اتبعت خطوات هذا الدرس, يجب ان يكون لديك اساس لعبة امر القذيفة باستخدام اطار عمل Sprite Kit. اذا كان لديك أي سؤال, لا تتردد بترك تعليق اسفلا.
ليست هناك تعليقات: