Construiți comanda rachetelor cu kitul Sprite configurare proiect

În acest tutorial, veți învăța cum să utilizați cadrul Sprite Kit al Apple pentru a recrea un joc de comandă pentru rachete pentru iPad. Pe parcurs, veți afla mai multe despre câteva concepte de bază, cum ar fi sprite, atingeri, fizică, coliziuni și explozii. Scopul celui de-al doilea tutorial este de a adăuga fizică, coliziuni și explozii. Al doilea tutorial extinde, de asemenea, experiența jocului prin adăugarea unui mod multi-player.


Amintiri

Vă amintiți comanda de rachete? Atari a lansat jocul original pe 8 martie 1981. A fost un joc de acțiune construit pentru sistemele Arcade și a devenit foarte popular în întreaga lume.

De la lansarea sa în 1981, au fost făcute mai multe adaptări pentru diferite platforme. Este timpul să recreați jocul original utilizând tehnologii moderne, iOS, Obiectiv-C și iPad.

Puteți juca în continuare jocul original. Uitați-vă la IGN și retrăiți câteva amintiri din copilărie.

Vizualizare finală

Imaginea de mai jos vă oferă o imagine a rezultatului final. Dacă vă place ceea ce vedeți, atunci să începem.



cerinţe

Pentru a finaliza acest tutorial, veți avea nevoie de Xcode 5 și cel mai recent SDK pentru iOS 7. Puteți descărca Xcode 5 și SDK din iOS Dev Center.

La sfârșitul fiecărei secțiuni, veți găsi una sau mai multe provocări. Obiectivul acestor provocări este de a vă ajuta să învățați tehnicile și tehnologiile utilizate în acest tutorial. Unele sunt ușor, în timp ce altele vor fi mai dificile, necesitând o bună înțelegere a cadrului Sprite Kit. Cu excepția ultimei provocări, rețineți că nu sunt necesare provocările pentru a finaliza tutorialul. Cu toate acestea, sperăm să le încercați.

Dacă aveți întrebări despre cadrul Sprite Kit, vă sugerăm să aruncați o privire la celelalte tutoriale ale Sprite Kit pe Mobiletuts+.


1. Configurarea proiectului

Lansați Xcode 5 și creați un nou proiect Sprite Kit selectând Nou> Proiect ... de la Fişier meniul. Alege Joc SpriteKit șablon, numele proiectului Comandamentul rachetelor, și selectați iPad din Dispozitive meniul.



Dacă aveți întrebări despre acest pas, vă recomandăm să citiți o explicație mai detaliată a acestui pas în Build a Game Airplane cu Sprite Kit - Setup Project.

Odată cu înființarea proiectului, adăugați resursele proiectului, pe care le puteți descărca utilizând link-ul din partea de sus a paginii. Vom începe prin a vă concentra pe Scena mea clasă. Interior MyScene.m, veți găsi două metode, initWithSize: și touchesBegan: withEvent:.

În initWithSize:, eliminați sau comentați codul care are legătură cu SKLabelNode deoarece nu avem nevoie de ea în acest tutorial. Uitați-vă la implementarea actualizată a initWithSize: de mai jos.

- (id) initWithSize: dimensiunea (CGSize) self = [super initWithSize: size]; dacă self.backgroundColor = [SKColor colorWithRed: 0.15 verde: 0.15 albastru: 0.3 alpha: 1.0];  întoarce-te; 

În touchesBegan: withEvent:, facem ceva similar. Pentru moment, metoda ar trebui să conțină numai logica pentru detectarea atingerii și localizarea atingerii utilizatorului. Aceste modificări vă vor oferi un avertisment de compilator, dar vom scăpa de asta mai târziu în acest tutorial.

- (void) atingeBegan: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment pentru (UITouch * atinge in atinge) CGPoint location = [touch locationInNode: self]; 

Următorul pas este să creați două clase noi. Prima clasă, MenuScene, va fi utilizat pentru meniul principal și pentru clasa a doua, MultiScene, vor fi folosite pentru interfața multiplayer. Ambele clase sunt subclase de SKScene. Scena mea clasa va fi utilizată pentru implementarea interfeței cu un singur jucător.

După cum am văzut în Scena mea , trebuie să implementăm un inițializator pentru fiecare clasă. Deocamdată, inițializatorul stabilește numai culoarea de fundal a scenei așa cum am văzut MyScene.m. Initializatorul programului MenuScene clasa trebuie să înființeze și titlul jocului. Pentru a face acest lucru, trebuie să avem grijă de câteva lucruri.

  • Creeaza o SKSpriteNode obiect.
  • Setați-o zPosition.
  • Setați-o scară.
  • Setați-o poziţie.
  • Adăugați obiectul ca un copil în clasă.

Aruncați o privire la punerea în aplicare a initWithSize: din MenuScene clasa pentru clarificare.

- (id) initWithSize: dimensiunea (CGSize) self = [super initWithSize: size]; dacă (auto) auto.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) verde: (220.0 / 255.0) albastru: (54.0 / 255.0) alfa: 1.0]; SKSpriteNode * titlu = [SKSpriteNode spriteNodeWithImageNamed: @ "titlu"]; title.zPosition = 2; title.scale = 0.4; title.position = CGPointMake (size.width / 2, size.height / 2); [self addChild: titlu];  întoarce-te; 

Ar trebui să aveți acum un meniu principal și un titlu. Este timpul să actualizați controlerul principal de vizualizare, astfel încât să fie afișat meniul de fiecare dată când aplicația este lansată. Deschis ViewController.m, localizați viewDidLoad și înlocuiți metoda SKScene exemplu cu o instanță a MenuScene clasa, după cum se arată mai jos.

- (vid) viewDidLoad [super viewDidLoad]; // Configurați vizualizarea. SKView * skView = (SKView *) auto-vizualizare; skView.showsFPS = DA; skView.showsNodeCount = DA; // Creați și configurați scena. SKScene * scena = [Scena MenuSceneWithSize: skView.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; // Prezentați scena. [skView prezentScene: scenă]; 

Nu uitați să importați fișierul antet al MenuScene clasă.

#import "ViewController.h" #import "MenuScene.h"

Grozav. Este timpul să vă construiți proiectul și să îl rulați pentru a verifica dacă totul funcționează corect. Ar trebui să vedeți o interfață asemănătoare capturii de ecran de mai jos.


Provocare: Pentru a crea o experiență unică, vă provocăm să faceți următoarele.

  • Modificați culorile de fundal pentru fiecare scenă.
  • Redați cu proprietățile MenuScene obiect titlu.

2. Obiecte, flori, monștri și rachete

Înainte de a adăuga obiecte la joc, trebuie să adăugăm abilitatea de a naviga în joc. Declarăți doi UIButton instanțe în MenuScene clasă și o variabilă, sizeGlobal, de tip CGSize pentru a stoca dimensiunea ecranului. Acesta din urmă ne va ajuta să poziționăm obiectele pe ecran. Actualizați MenuScene.m așa cum se arată mai jos.

#import "MenuScene.h" @interface MenuScene () CGSize sizeGlobal; UIButton * singlePlayerButton; UIButton * multiPlayerButton;  @Sfârșit

A stabilit sizeGlobal la mărimea în inițialele clasei, după cum se arată în fragmentul de cod de mai jos.

- (id) initWithSize: dimensiunea (CGSize) self = [super initWithSize: size]; dacă (auto) auto.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) verde: (220.0 / 255.0) albastru: (54.0 / 255.0) alfa: 1.0]; SKSpriteNode * titlu = [SKSpriteNode spriteNodeWithImageNamed: @ "titlu"]; title.zPosition = 2; title.scale = 0.4; title.position = CGPointMake (size.width / 2, size.height / 2); [self addChild: titlu]; sizeGlobal = size;  întoarce-te; 

Apoi, declarați trei metode în MenuScene clasă.

  • didMoveToView: pentru a prezenta butoanele atunci când jocul trece în vizualizarea meniului.
  • moveToSinglePlayerGame care tranzitează jocul la Scena mea scena și elimină butoanele.
  • moveToMultiPlayerGame care tranzitează jocul la MultiScene scena și, de asemenea, elimină butoanele.

În didMoveToView:, aplicația verifică dacă tranziția scenariului a avut loc fără probleme. Dacă nu au apărut probleme, aplicația încarcă resursele, le afișează utilizatorului și instantează butoanele.

- (void) didMoveToView: (SKView *) vizualizare UIImage * buttonImageNormal = [UIImage imageNamed: @ "singleBtn.png"]; singlePlayerButton = [butonul UIButtonWithType: UIButtonTypeRoundedRect]; singlePlayerButton.frame = CGRectMake (dimensiuneGlobal.height / 8, sizeGlobal.width / 2 + 250, buttonImageNormal.size.width, buttonImageNormal.size.height); singlePlayerButton.backgroundColor = [UICcolor clearColor]; [singlePlayerButton setTitleColor: [UICcolor whiteColor] pentruState: UIControlStateNormal]; UIImage * strechableButtonImageNormal = [butonulImageNormal stretchableImageWithLeftCapWidth: 12 topCapHeight: 0]; [singlePlayerButton setBackgroundImage: strechableButtonImageNormal forState: UIControlStateNormal]; [singlePlayerButton addTarget: acțiunea individuală: @selector (moveToSinglePlayerGame) forControlEvents: UIControlEventTouchUpInside]; [self.view addSubview: singlePlayerButton]; UIImage * buttonImageNormal2 = [UIImage imageNamed: @ "multiBtn.png"]; multiPlayerButton = [butonul UIButtonWithType: UIButtonTypeRoundedRect]; multiPlayerButton.frame = CGRectMake (dimensiuneGlobal.height / 2 + 100, dimensiuneGlobal.width / 2 + 250, buttonImageNormal2.size.width, buttonImageNormal2.size.height); multiPlayerButton.backgroundColor = [UICcolor clearColor]; [multiPlayerButton setTitleColor: [UICcolor whiteColor] pentruState: UIControlStateNormal]; UIImage * strechableButtonImageNormal2 = [butonulImageNormal2 stretchableImageWithLeftCapWidth: 12 topCapHeight: 0]; [multiPlayerButton setBackgroundImage: strechableButtonImageNormal2 forState: UIControlStateNormal]; [multiPlayerButton addTarget: acțiune individuală: @selector (moveToMultiPlayerGame) forControlEvents: UIControlEventTouchUpInside]; [auto.view addSubview: multiPlayerButton]; 

În didMoveToView:, noi sunam moveToSinglePlayerGame și moveToMultiPlayerGame. Să implementăm următoarele metode. În fiecare metodă, trebuie să facem următoarele.

  • Creați o instanță a fiecăruia Scena mea sau MultiScene.
  • Creați o tranziție scenă.
  • Prezentați noua scenă.
  • Scoateți butoanele.

Puteți implementa aceste metode pe cont propriu? Dacă nu sunteți sigur, aruncați o privire la implementările de mai jos.

- (void) moveToSinglePlayerGame SKScene * scena = [MyScene sceneWithSize: self.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; SKTransition * tranziție = [SKTransition revealWithDirection: SKTransitionDirectionLeft length: 1]; SKView * skView = (SKView *) auto-vizualizare; [skView prezentScene: tranziție scenă: tranziție]; [singlePlayerButton removeFromSuperview]; [multiPlayerButton removeFromSuperview]; 
- (void) moveToMultiPlayerGame SKScene * scena = [MultiScene sceneWithSize: self.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; SKTransition * tranziție = [SKTransition revealWithDirection: SKTransitionDirectionLeft length: 1]; SKView * skView = (SKView *) auto-vizualizare; [skView prezentScene: tranziție scenă: tranziție]; [singlePlayerButton removeFromSuperview]; [multiPlayerButton removeFromSuperview]; 

Nu uitați să adăugați o declarație de import pentru fișierele antet din Scena mea și MultiScene.

#import "MenuScene.h" #import "MyScene.h" #import "MultiScene.h" @interface MeniuScene () CGSize sizeGlobal; UIButton * singlePlayerButton; UIButton * multiPlayerButton;  @Sfârșit

Construiți-vă proiectul și rulați aplicația în Simulatorul iOS sau pe un dispozitiv fizic. Jocul ar trebui să pară asemănător capturii de ecran de mai jos.


Meniul principal este terminat. Este timpul să vă concentrați asupra interfeței cu un singur jucător a jocului (Scena mea). Scena mea clasa va conține cea mai mare parte a logicii jocului. Primul pas este să poziționați florile de tip glonț din partea de jos a ecranului. Vom crea trei flori, fiecare dintre acestea având proprietăți unice.

Veți urmări, de asemenea, numărul de rachete explodate și afișați acea valoare în altul SKLabelNode numit labelMissilesExploded. După cum puteți vedea mai jos, vom avea nevoie de o serie de variabile de instanță sau Ivars. Scopul fiecărui ivar va deveni clar atunci când vom actualiza initWithSize: metoda în Scena mea.

#import "MyScene.h" @interface MyScene () CGSize sizeGlobal; SKLabelNode * labelflowerBullets1; SKLabelNode * labelflowerBullets2; SKLabelNode * labelflowerBullets3; SKLabelNode * labelMissilesExploded; int; int monstersDead; int rachetăExplodată; int flowerBullets1; int flowerBullets2; int flowerBullets3;  @Sfârșit

În initWithSize:, noi instanțiăm și configurăm diferitele SKLabelNode instanțe.

- (dimensiune CGSize) if (auto = [super initWithSize: dimensiune]) auto.backgroundColor = [SKColor colorWithRed: (220.0 / 255.0) verde: (220.0 / 255.0) : 1,0]; pozitie = dimensiune.width / 3; sizeGlobal = size; [self addFlowerCommand]; // Etichete de informare a rachetelor etichete explodateMissilesExploded = [SKLabelNode labelNodeWithFontNamed: @ "Hiragino-Kaku-Gothic-ProN"]; labelMissilesExploded.text = [șir NSStringWithFormat: @ "rachete explodate:% d", rachetăexpusă]; labelMissilesExploded.fontSize = 30; etichetaMissilesExploded.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 șirWithFormat: @ "% d", flowerBullets1]; labelflowerBullets1.fontSize = 30; labelflowerBullets1.position = CGPointMake (poziție-poziție / 2, labelflowerBullets1.frame.size.height / 2); labelflowerBullets1.zPosition = 3; [self addChild: labelflowerBullets1]; labelflowerBullets2 = [SKLabelNode labelNodeWithFontNamed: @ "Hiragino-Kaku-Gothic-ProN"]; labelflowerBullets2.text = [NSString șirWithFormat: @ "% d", flowerBullets2]; labelflowerBullets2.fontSize = 30; labelflowerBullets2.position = CGPointMake (pozitia * 2-pozitie / 2, labelflowerBullets2.frame.size.height / 2); labelflowerBullets2.zPosition = 3; [self addChild: labelflowerBullets2]; labelflowerBullets3 = [SKLabelNode labelNodeWithFontNamed: @ "Hiragino-Kaku-Gothic-ProN"]; labelflowerBullets3.text = [NSString șirWithFormat: @ "% d", flowerBullets3]; labelflowerBullets3.fontSize = 30; labelflowerBullets3.position = CGPointMake (pozitia * 3-pozitie / 2, labelflowerBullets3.frame.size.height / 2); labelflowerBullets3.zPosition = 3; [self addChild: labelflowerBullets3];  întoarce-te; 

În initWithSize:, suntem, de asemenea, de apel addFlowerCommand, pe care nu am acoperit încă. Implementarea nu este dificilă, după cum puteți vedea mai jos. În addFlowerCommand, instanțiăm trei SKSpriteNode câte unul pentru fiecare floare, și poziționați-le în partea de jos a ecranului cu ajutorul poziţie.

- (void) addFlowerCommand pentru (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];  

Acum puteți construi proiectul și îl puteți rula în simulatorul iOS pentru a vedea interfața jocului cu un singur jucător.

Avem flori, dar mai avem nevoie de niște monștri. Este timpul să pună în aplicare addMonstersBetweenSpace: metodă. În această metodă, creăm trei monștri și le poziționăm între flori. Poziția monștrilor este determinată de spaceOrder variabil. Poziționăm aleatoriu monștrii folosind getRandomNumberBetween: la:, care generează un număr aleator între două numere date.

- (void) addMonstersBetweenSpace: (int) spaceOrder pentru (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];  

Implementarea sistemului getRandomNumberBetween: la: este prezentat mai jos.

- (int) getRandomNumber Între: (int) de la la: (int) la return (int) de la + arc4random ()% (la - de la + 1); 

Noi invocăm addMonstersBetweenSpace: de două ori în initWithSize: metodă a Scena mea clasă.

- (dimensiune CGSize) if (auto = [super initWithSize: dimensiune]) auto.backgroundColor = [SKColor colorWithRed: (220.0 / 255.0) verde: (220.0 / 255.0) : 1,0]; // ... // // Adăugați monștrii [self addMonstersBetweenSpace: 1]; [auto adăugaMonstersBetweenSpace: 2];  întoarce-te; 

Acum că avem flori și monștri, este timpul să adăugăm rachetele. Trebuie să facem următoarele pentru a realiza acest lucru.

  • Creaza un SKAction să invocați o metodă.
  • Creaza un SKAction pentru a repeta acea acțiune.
  • aplica addMissilesFromSky:, care va genera la întâmplare trei rachete noi și le va adăuga la scenă.

Vom declara SKAction instances in initWithSize:. Uitați-vă la implementarea actualizată a initWithSize: de mai jos.

- (dimensiune CGSize) if (auto = [super initWithSize: dimensiune]) auto.backgroundColor = [SKColor colorWithRed: (220.0 / 255.0) verde: (220.0 / 255.0) : 1,0]; // ... // // Creați acțiuni SKAction * așteptați = [SKAction waitForDuration: 2]; SKAction * createMissiles = [SKAction runBlock: ^ [self addMissilesFromSky: size]; ]; SKAction * updateMissiles = [Succesiune: @ [wait, createMissiles]]; [auto runAction: [repetActionFactor repeatAction: updateMissiles]];  întoarce-te; 

Implementarea sistemului addMissilesFromSky: este prezentat mai jos.

- (void) addMissilesFromSky: (CGSize) dimensiunea int numberMissiles = [get getRandomNumber între 0 și 3]; pentru (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];  

Dacă construiți și executați aplicația, rezultatul ar trebui să arate similar cu imaginea de mai jos.


Provocare: Acest lucru este minunat, dar avem nevoie de mai mulți monștri. Vă provocăm să faceți următoarele.

  • Adăugați mai mulți monștri.
  • Adăugați mai multe flori.
  • Modificați mișcarea rachetelor.

3. Interacțiunea cu utilizatorul

Putem vedea o mișcare, dar avem nevoie de componenta cheie a jocului, interacțiunea cu utilizatorul. Adăugăm interacțiunea cu utilizatorii prin utilizarea a două metode, touchesBegan: withEvent: și positionOfWhichFlowerShouldBegin:. Pentru a adăuga interacțiunea cu utilizatorul, trebuie să luăm în considerare următoarele aspecte.

  • Fiecare floare poate trage doar zece gloante.
  • Trebuie să detectați locația atingerii utilizatorului și să utilizați cea mai apropiată floare pentru a trage glonțul.
  • Glonțul ar trebui să treacă la locația atingerii utilizatorului.
  • Glonțul ar trebui să explodeze la locul atingerii utilizatorului.

Implementarea actualizată a touchesBegan: withEvent: este prezentat mai jos.

- (void) atingeBegan: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment pentru (UITouch * atinge in atinge) CGPoint location = [touch locationInNode: self]; // Intoarceti-va in cazul in care utilizatorul bate sub o floare daca (location.y < 120) return; int bulletBeginning = 0; if (location.x >= 0 && location.x < position)  bulletBeginning = position-position/2; if (flowerBullets1 > 0) flowerBullets1--; altceva if (flowerBullets1 == 0 && flowerBullets2> 0) flowerBullets2--; [labelflowerBullets2 setText: [NSString șirWithFormat: @ "% d", flowerBullets2]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 2];  altfel dacă (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString șirWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 3];  altceva return;  [labelflowerBullets1 setText: [NSString șirWithFormat: @ "% d", flowerBullets1]];  altfel dacă ((location.x> = position && location.x < position*2)) bulletBeginning = position*2-position/2; if(flowerBullets2 > 0) flowerBullets2--; altceva if (location.x < sizeGlobal.width/2) if(flowerBullets1 > 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString șirWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 1];  altfel dacă (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString șirWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 3];  altceva return;  altceva if (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString șirWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 3];  altfel dacă (flowerBullets1> 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString șirWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 1];  altceva return;  [labelflowerBullets2 setText: [NSString șirWithFormat: @ "% d", flowerBullets2]];  altceva bulletBeginning = poziție * 3-poziție / 2; dacă (flowerBullets3> 0) flowerBullets3--; altceva if (flowerBullets3 == 0 && flowerBullets2> 0) flowerBullets2--; [labelflowerBullets2 setText: [NSString șirWithFormat: @ "% d", flowerBullets2]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 2];  altfel dacă (flowerBullets1> 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString șirWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [poziția proprieDe ceFlowerShouldBegin: 1];  altceva return;  [labelflowerBullets3 setText: [NSString șirWithFormat: @ "% d", flowerBullets3]]; 

Chiar dacă este o mulțime de cod pentru a trece prin, nu este atât de complicat. Verificați dacă există gloanțe rămase pentru fiecare floare și detectați zona în care utilizatorul a apelat prin invocarea positionOfWhichFlowerShouldBegin:, pe care o vom discuta într-un moment. În același timp, verificăm dacă utilizatorul a lovit sub floare, ceea ce împiedică floarea să tragă un glonț.

dacă (location.y < 120) return;

positionOfWhichFlowerShouldBegin: metoda returnează poziția care corespunde unei zone specifice în care utilizatorul a atins. Amintiți-vă că ați împărțit ecranul în trei părți pentru a poziționa cele trei flori, astfel încât va trebui să detectați zona în care utilizatorul a bătut și să-l legați de una dintre flori. Floarea care împușcă glonțul va fi cea mai apropiată de robinetul utilizatorului. Aceasta este ceea ce punerea în aplicare a positionOfWhichFlowerShouldBegin: se pare ca.

- (int) positionOfWhichFlowerShouldBegin: (int) numărul retur poziție * număr - poziție / 2; 

Pentru a face gloanțele să se miște, trebuie să creăm un altul SKSpriteNode instanță. Fiecare glonț are o durată și un an SKAction asociate cu acesta. Această logică este, de asemenea, inclusă în touchesBegan: withEvent:. Uitați-vă la implementarea actualizată de mai jos.

- (void) atingeBegan: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment pentru (UITouch * atinge in atinge) CGPoint location = [touch locationInNode: self]; // ... // SKSpriteNode * bullet = [SKSpriteNode spriteNodeWithImageNamed: @ "floareBullet"]; bullet.zPosition = 1; bullet.scale = 0.6; bullet.position = CGPointMake (bulletBeginning, 110); bullet.color = [SKColor redColor]; bullet.colorBlendFactor = 0.5; durata flotantului = (2 * location.y) /sizeGlobal.width; SKAction * move = [deplasare SKActionTo: CGPointMake (location.x, location.y) duration: duration]; SKAction * remove = [SKAction removeFromParent]; [bullet runAction: [secvența SKAction: @ [move, remove]]; [self addChild: bullet]; 

Dacă construiți și rulați aplicația dvs., florile ar trebui să poată trage gloanțe. Nu explodează încă, dar vom avea grijă de asta în următorul tutorial.


Provocare: Ești pregătit pentru o altă provocare? Uitați-vă la aceste provocări.

  • Creați și definiți diferite mișcări de gloanțe.
  • Modificați durata mișcării fiecărui glonț.

Concluzie

Dacă ați urmat pașii din acest tutorial, acum ar trebui să aveți fundația jocului Comandă de rachete folosind cadrul Sprite Kit. Dacă aveți întrebări sau feedback, vă rugăm să lăsați un comentariu mai jos.

Cod