Bygg Missile Command med Sprite Kit Prosjektoppsett

I denne opplæringen lærer du hvordan du bruker Apples Sprite Kit-rammeverk for å gjenopprette et Missile Command-spill for iPad. Underveis lærer du mer om flere kjernekonsepter som sprites, berøringer, fysikk, kollisjoner og eksplosjoner. Målet med den andre opplæringen er å legge til fysikk, kollisjoner og eksplosjoner. Den andre opplæringen utvider også spillopplevelsen ved å legge til en flerspiller-modus.


minner

Husker du Missile Command? Atari ga ut det opprinnelige spillet 8. mars 1981. Det var et actionspill bygget for Arcade-systemer og ble svært populært rundt om i verden.

Siden utgivelsen i 1981 ble det gjort flere tilpasninger for ulike plattformer. Nå er det tid for deg å gjenskape det opprinnelige spillet ved hjelp av moderne teknologier, iOS, Objective-C og iPad.

Du kan fortsatt spille det opprinnelige spillet. Ta en titt over på IGN og gjenopplev noen av barndommens minner.

Endelig forhåndsvisning

Skjermbildet under gir deg en ide om hvordan sluttresultatet vil se ut. Hvis du liker det du ser, så la oss komme i gang.



Krav

For å fullføre denne opplæringen trenger du Xcode 5 og den nyeste iOS 7 SDK. Du kan laste ned Xcode 5 og SDK fra iOS Dev Center.

På slutten av hvert avsnitt finner du en eller flere utfordringer. Målet med disse utfordringene er å hjelpe deg med å lære teknikker og teknologier som brukes i denne opplæringen. Noen er enkle, mens andre blir mer utfordrende, og krever en god forståelse av Sprite Kit-rammen. Med unntak av den siste utfordringen, husk at utfordringene ikke er nødvendige for å fullføre opplæringen. Men vi håper du gir dem en prøve.

Hvis du har spørsmål om Sprite Kit-rammeverket, foreslår vi at du tar en titt på våre andre Sprite Kit-veiledninger på Mobiletuts+.


1. Prosjektoppsett

Start Xcode 5 og opprett et nytt Sprite Kit-prosjekt ved å velge Nytt> Prosjekt ... fra Fil Meny. Velg SpriteKit Game mal, nevne prosjektet ditt Rakettkommando, og velg iPad fra enheter Meny.



Hvis du har spørsmål om dette trinnet, oppfordrer vi deg til å lese en mer detaljert forklaring av dette trinnet i Bygg et flyspill med Sprite Kit - Prosjektoppsett.

Med prosjektet satt opp, legg til prosjektets ressurser, som du kan laste ned ved hjelp av linken øverst på siden. Vi starter med å fokusere på MyScene klasse. Innsiden MyScene.m, Du finner to metoder, initWithSize: og touchesBegan: withEvent:.

I initWithSize:, fjern eller kommentere koden som er relatert til SKLabelNode eksempel som vi ikke trenger det i denne opplæringen. Ta en titt på den oppdaterte implementeringen av initWithSize: under.

- (id) initWithSize: (CGSize) størrelse self = [super initWithSize: size]; hvis (selv) self.backgroundColor = [SKColor colorWithRed: 0.15 green: 0.15 blue: 0.3 alpha: 1.0];  returner selv; 

I touchesBegan: withEvent:, vi gjør noe lignende. For nå må metoden bare inneholde logikken for berøringsdeteksjon og plasseringen av brukerens berøring. Disse endringene vil gi deg en kompilervarsel, men vi vil bli kvitt det senere i denne opplæringen.

- (void) berørerBegan: (NSSet *) berører withEvent: (UIEvent *) hendelse for (UITouch * berør berøring) CGPoint location = [touch locationInNode: self]; 

Ditt neste skritt er å skape to nye klasser. Den første klassen, MenuScene, vil bli brukt til hovedmenyen og andre klasse, multiscene, vil bli brukt til multiplayer grensesnittet. Begge klassene er underklasser av SKScene. De MyScene klassen vil bli brukt til å implementere singleplayer grensesnittet.

Som vi så i MyScene klasse, må vi implementere en initialiserer for hver klasse. For nå setter initialisereren bare scenens bakgrunnsfarge som vi så i MyScene.m. Initialiseringen av MenuScene klassen må også sette opp spilltittelen. For å gjøre det, må vi ta vare på noen få ting.

  • Lage en SKSpriteNode gjenstand.
  • Sett sin zPosition.
  • Sett sin skala.
  • Sett sin stilling.
  • Legg objektet som barn i klassen.

Ta en titt på implementeringen av initWithSize: av MenuScene klasse for avklaring.

- (id) initWithSize: (CGSize) størrelse self = [super initWithSize: size]; hvis (selv) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) grønn: (220.0 / 255.0) blå: (54.0 / 255.0) alfa: 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];  returner selv; 

Du bør nå ha en hovedmeny og en tittel. Det er på tide å oppdatere hovedvisningskontrollen slik at den viser menyen hver gang programmet startes. Åpen ViewController.m, finn viewDidLoad metode, og erstatte SKScene eksempel med en forekomst av MenuScene klassen som vist nedenfor.

- (void) viewDidLoad [super viewDidLoad]; // Konfigurer visningen. SKView * skView = (SKView *) self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; // Opprett og konfigurer scenen. SKScene * scene = [Menyscene sceneWithSize: skView.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; // Presentere scenen. [skView presentScene: scene]; 

Ikke glem å importere headerfilen til MenuScene klasse.

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

Flott. Det er på tide å bygge prosjektet ditt og kjøre det for å kontrollere at alt fungerer som det skal. Du bør se et grensesnitt som ligner skjermbildet nedenfor.


Utfordring: For å skape en unik opplevelse, utfordrer vi deg til å gjøre følgende.

  • Endre bakgrunnsfargene til hver scene.
  • Spill med egenskapene til MenuScene tittelobjekt.

2. Objekter, blomster, monstre og missiler

Før du legger til objekter i spillet, må vi legge til evnen til å navigere i spillet. Erklære to UIButton forekomster i MenuScene klasse og en variabel, sizeGlobal, av type CGSize for å lagre størrelsen på skjermen. Sistnevnte vil hjelpe oss med å posisjonere objektene på skjermen. Oppdater MenuScene.m som vist under.

#import "MenuScene.h" @interface MenuScene () CGSize sizeGlobal; UIButton * singlePlayerButton; UIButton * multiPlayerButton;  @slutt

Sett sizeGlobal til størrelse i klassens initialiserer som vist i kodestykket nedenfor.

- (id) initWithSize: (CGSize) størrelse self = [super initWithSize: size]; hvis (selv) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) grønn: (220.0 / 255.0) blå: (54.0 / 255.0) alfa: 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;  returner selv; 

Deretter erklæres tre metoder i MenuScene klasse.

  • didMoveToView: å presentere knappene når spillet overgår til menyvisningen.
  • moveToSinglePlayerGame som overgår spillet til MyScene scene og fjerner knappene.
  • moveToMultiPlayerGame som overgår spillet til multiscene scene og fjerner også knappene.

I didMoveToView:, programmet verifiserer om scenen overgangen fant sted uten problemer. Hvis det ikke oppstod noen problemer, laster applikasjonen ressursene, viser dem til brukeren og instanser knappene.

- (void) didMoveToView: (SKView *) visning 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: selvhandling: @selector (moveToSinglePlayerGame) forControlEvents: UIControlEventTouchUpInside]; [self.view addSubview: singlePlayerButton]; Ullmage * 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: selvhandling: @selector (moveToMultiPlayerGame) forControlEvents: UIControlEventTouchUpInside]; [self.view addSubview: multiPlayerButton]; 

I didMoveToView:, vi ringer moveToSinglePlayerGame og moveToMultiPlayerGame. La oss implementere disse metodene neste. I hver metode må vi gjøre følgende.

  • Lag en forekomst av enten MyScene eller multiscene.
  • Lag en sceneovergang.
  • Presenter den nye scenen.
  • Fjern knappene.

Kan du implementere disse metodene alene? Hvis du er usikker, ta en titt på implementeringene nedenfor.

- (void) moveToSinglePlayerGame SKScene * scene = [MyScene sceneWithSize: self.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; SKTransition * overgang = [SKTransition revealWithDirection: SKTransitionDirectionLeft varighet: 1]; SKView * skView = (SKView *) self.view; [skView presentScene: sceneovergang: overgang]; [singlePlayerButton removeFromSuperview]; [multiPlayerButton removeFromSuperview]; 
- (void) moveToMultiPlayerGame SKScene * scene = [MultiScene sceneWithSize: self.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; SKTransition * overgang = [SKTransition revealWithDirection: SKTransitionDirectionLeft varighet: 1]; SKView * skView = (SKView *) self.view; [skView presentScene: sceneovergang: overgang]; [singlePlayerButton removeFromSuperview]; [multiPlayerButton removeFromSuperview]; 

Ikke glem å legge til en importerklæring for headerfiler av MyScene og multiscene.

#import "MenuScene.h" #import "MyScene.h" #import "MultiScene.h" @interface MenuScene () CGSize sizeGlobal; UIButton * singlePlayerButton; UIButton * multiPlayerButton;  @slutt

Bygg prosjektet ditt og kjør programmet i iOS-simulatoren eller på en fysisk enhet. Spillet skal nå se ut som skjermbildet nedenfor.


Hovedmenyen er ferdig. Det er på tide å fokusere på spillets singleplayer-grensesnitt (MyScene). De MyScene klassen vil inneholde det meste av spillets logikk. Det første trinnet er å plassere kulefotograferingsblomstene nederst på skjermen. Vi lager tre blomster, som hver vil ha unike egenskaper.

Du vil også spore antall eksploderte missiler og vise den verdien i en annen SKLabelNode oppkalt labelMissilesExploded. Som du kan se nedenfor, trenger vi en rekke instansvariabler eller ivars. Hensikten med hver ivar blir klar når vi oppdaterer initWithSize: metode i MyScene.

#import "MyScene.h" @interface MyScene () CGSize sizeGlobal; SKLabelNode * labelflowerBullets1; SKLabelNode * labelflowerBullets2; SKLabelNode * labelflowerBullets3; SKLabelNode * labelMissilesExploded; int posisjon; int monstersDead; int missileExploded; int flowerBullets1; int flowerBullets2; int flowerBullets3;  @slutt

I initWithSize:, Vi instantierer og konfigurerer de ulike SKLabelNode forekomster.

- (id) initWithSize: (CGSize) størrelse if (selv = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) grønn: (220.0 / 255.0) blå: (54.0 / 255.0) alpha : 1,0]; posisjon = size.width / 3; sizeGlobal = size; [self addFlowerCommand]; // Etikett Informere Missiler Sprengt labelMissilesExploded = [SKLabelNode labelNodeWithFontNamed: @ "Hiragino-Kaku-Gothic-ProN"]; labelMissilesExploded.text = [NSString stringWithFormat: @ "Missiler eksplodert:% 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 (posisjon-posisjon / 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 (posisjon * 2-posisjon / 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 (posisjon * 3-posisjon / 2, labelflowerBullets3.frame.size.height / 2); labelflowerBullets3.zPosition = 3; [self addChild: labelflowerBullets3];  returner selv; 

I initWithSize:, vi ringer også addFlowerCommand, som vi ikke har dekket ennå. Implementeringen er ikke vanskelig som du kan se nedenfor. I addFlowerCommand, vi instanser tre SKSpriteNode forekomster, en for hver blomst, og plasser dem nederst på skjermen ved hjelp av stilling.

- (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];  

Du kan nå bygge prosjektet og kjøre det i iOS Simulator for å se spillets enkeltspiller grensesnitt.

Vi har blomster, men vi trenger fortsatt noen monstre. Det er på tide å gjennomføre addMonstersBetweenSpace: metode. I denne metoden lager vi tre monstre og plasserer dem mellom blomstene. Monsternes posisjon bestemmes av spaceOrder variabel. Vi plasserer tilfeldigvis monstrene ved å bruke getRandomNumberBetween: til:, som genererer et tilfeldig tall mellom to gitt tall.

- (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];  

Gjennomføringen av getRandomNumberBetween: til: er vist nedenfor.

- (int) getRandomNumberBetween: (int) fra til: (int) til return (int) fra + arc4random ()% (til - fra + 1); 

Vi påberoper addMonstersBetweenSpace: to ganger i initWithSize: metode av MyScene klasse.

- (id) initWithSize: (CGSize) størrelse if (selv = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) grønn: (220.0 / 255.0) blå: (54.0 / 255.0) alpha : 1,0]; // ... // // Legg til Monsters [self addMonstersBetweenSpace: 1]; [self addMonstersBetweenSpace: 2];  returner selv; 

Nå som vi har blomster og monstre, er det på tide å legge til missiler. Vi må gjøre følgende for å oppnå dette.

  • Lag en SKAction å påberope en metode.
  • Lag en SKAction å gjenta denne handlingen.
  • Implementere addMissilesFromSky:, som vil tilfeldig generere tre nye raketter og legge dem til scenen.

Vi vil erklære SKAction forekomster i initWithSize:. Ta en titt på den oppdaterte implementeringen av initWithSize: under.

- (id) initWithSize: (CGSize) størrelse if (selv = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) grønn: (220.0 / 255.0) blå: (54.0 / 255.0) alpha : 1,0]; // ... // // Opprett handlinger SKAction * wait = [SKAction waitForDuration: 2]; SKAction * createMissiles = [SKAction runBlock: ^ [self addMissilesFromSky: size]; ]; SKAction * updateMissiles = [SKAction sekvens: @ [vent, createMissiles]]; [self runAction: [SKAction repeatActionForever: updateMissiles]];  returner selv; 

Gjennomføringen av addMissilesFromSky: er vist nedenfor.

- (void) addMissilesFromSky: (CGSize) størrelse 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];  

Hvis du bygger og kjører din søknad, bør resultatet se ut som skjermbildet nedenfor.


Utfordring: Dette er flott, men vi trenger virkelig flere monstre. Vi utfordrer deg til å gjøre følgende.

  • Legg til flere monstre.
  • Legg til flere blomster.
  • Endre bevegelsen av missiler.

3. Brukerinteraksjon

Vi kan se litt bevegelse, men vi trenger nøkkelkomponenten i spillet, brukerinteraksjon. Vi legger til brukerinteraksjon ved å utnytte to metoder, touchesBegan: withEvent: og positionOfWhichFlowerShouldBegin:. For å legge til brukerinteraksjon må vi ta hensyn til følgende.

  • Hver blomst kan bare skyte ti kuler.
  • Du må oppdage plasseringen av brukerens berøring og bruke nærmeste blomst for å skyte kulen.
  • Kulen skal flytte til plasseringen av brukerens berøring.
  • Kulen skal eksplodere på stedet av brukerens berøring.

Den oppdaterte implementeringen av touchesBegan: withEvent: er vist nedenfor.

- (void) berørerBegan: (NSSet *) berører withEvent: (UIEvent *) hendelse for (UITouch * berør berøring) CGPoint location = [touch locationInNode: self]; // Returner om brukerkraner under en blomst hvis (location.y < 120) return; int bulletBeginning = 0; if (location.x >= 0 && location.x < position)  bulletBeginning = position-position/2; if (flowerBullets1 > 0) flowerBullets1--; ellers if (flowerBullets1 == 0 && flowerBullets2> 0) flowerBullets2--; [labelflowerBullets2 setText: [NSString stringWithFormat: @ "% d", flowerBullets2]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 2];  annet hvis (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 3];  ellers return;  [labelflowerBullets1 setText: [NSString stringWithFormat: @ "% d", flowerBullets1]];  annet hvis ((location.x> = posisjon && location.x < position*2)) bulletBeginning = position*2-position/2; if(flowerBullets2 > 0) flowerBullets2--; ellers hvis (sted.x < sizeGlobal.width/2) if(flowerBullets1 > 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString stringWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 1];  annet hvis (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 3];  ellers return;  else if (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 3];  annet hvis (flowerBullets1> 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString stringWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 1];  ellers return;  [labelflowerBullets2 setText: [NSString stringWithFormat: @ "% d", flowerBullets2]];  else bulletBeginning = posisjon * 3-posisjon / 2; hvis (flowerBullets3> 0) flowerBullets3--; ellers if (flowerBullets3 == 0 && flowerBullets2> 0) flowerBullets2--; [labelflowerBullets2 setText: [NSString stringWithFormat: @ "% d", flowerBullets2]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 2];  annet hvis (flowerBullets1> 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString stringWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [selvposisjonOfWhichFlowerShouldBegin: 1];  ellers return;  [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; 

Selv om det er mye kode for å gå gjennom, er det ikke så komplisert. Du kontrollerer om det er noen kuler igjen for hver blomst og oppdag sonen der brukeren tappet ved å påkalle positionOfWhichFlowerShouldBegin:, som vi skal diskutere om et øyeblikk. Samtidig kontrollerer vi om brukeren tappet under blomsten, noe som forhindrer blomsten i å skyte en kule.

hvis (location.y < 120) return;

De positionOfWhichFlowerShouldBegin: Metoden returnerer posisjonen som tilsvarer en bestemt sone der brukeren har tappet. Husk at du delte skjermen i tre deler for å plassere de tre blomstene, slik at du må oppdage sonen der brukeren har tappet og lenke den til en av blomstene. Blomsten som skyter kulen, vil være den nærmeste til brukerens trykk. Dette er hva implementeringen av positionOfWhichFlowerShouldBegin: ser ut som.

- (int) posisjonOfWhichFlowerShouldBegin: (int) nummer returposisjon * nummer - posisjon / 2; 

For å få kulene til å flytte, må vi opprette en annen SKSpriteNode forekomst. Hver kule har en varighet og en SKAction forbundet med det. Denne logikken er også inkludert i touchesBegan: withEvent:. Ta en titt på den oppdaterte gjennomføringen nedenfor.

- (void) berørerBegan: (NSSet *) berører withEvent: (UIEvent *) hendelse for (UITouch * berør berøring) 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) varighet: varighet]; SKAction * remove = [SKAction removeFromParent]; [bullet runAction: [SKAction sekvens: @ [move, remove]]]; [self addChild: bullet]; 

Hvis du bygger og driver søknaden din, bør blomstene kunne skyte kuler. De eksploderer ikke ennå, men vi tar vare på det i neste opplæring.


Utfordring: Er du opp for en annen utfordring? Ta en titt på disse utfordringene.

  • Lag og definer ulike kuldebevegelser.
  • Endre varigheten av bevegelsen til hver kule.

Konklusjon

Hvis du har fulgt trinnene i denne opplæringen, bør du nå ha grunnlaget for Missile Command-spillet ved hjelp av Sprite Kit-rammen. Hvis du har spørsmål eller tilbakemelding, er du velkommen til å legge igjen en kommentar nedenfor.