In questo tutorial imparerai come utilizzare il framework Sprite Kit di Apple per ricreare un gioco Missile Command per iPad. Lungo la strada, imparerai di più su diversi concetti chiave come sprite, tocchi, fisica, collisioni ed esplosioni. L'obiettivo del secondo tutorial è aggiungere fisica, collisioni ed esplosioni. Il secondo tutorial espande anche l'esperienza di gioco aggiungendo una modalità multi-player.
Ti ricordi il comando missilistico? Atari ha rilasciato il gioco originale l'8 marzo 1981. È stato un gioco d'azione costruito per i sistemi Arcade ed è diventato molto popolare in tutto il mondo.
Dalla sua uscita nel 1981, vari adattamenti furono fatti per varie piattaforme. È giunto il momento per te di ricreare il gioco originale utilizzando tecnologie moderne, iOS, Objective-C e iPad.
Puoi ancora giocare al gioco originale. Dai un'occhiata a IGN e rivivi alcuni dei tuoi ricordi d'infanzia.Lo screenshot qui sotto ti dà un'idea di come sarà il risultato finale. Se ti piace quello che vedi, allora iniziamo.
Per completare questo tutorial, avrai bisogno di Xcode 5 e dell'ultimo iOS 7 SDK. Puoi scaricare Xcode 5 e SDK dal Dev Center di iOS.
Alla fine di ogni sezione, troverai una o più sfide. L'obiettivo di queste sfide è quello di aiutarti a imparare le tecniche e le tecnologie utilizzate in questo tutorial. Alcuni sono facili mentre altri saranno più impegnativi, richiedendo una buona conoscenza del framework di Sprite Kit. Ad eccezione dell'ultima sfida, ricorda che le sfide non sono richieste per completare il tutorial. Tuttavia, speriamo che provi.
Se hai domande sul framework Sprite Kit, ti suggeriamo di dare un'occhiata agli altri tutorial di Sprite Kit su Mobiletuts+.
Avvia Xcode 5 e crea un nuovo progetto Sprite Kit selezionando Nuovo> Progetto ... dal File menu. Scegli il SpriteKit Game modello, assegna un nome al tuo progetto Comando missilistico, e seleziona iPad dal dispositivi menu.
Con il progetto impostato, aggiungi le risorse del progetto, che puoi scaricare utilizzando il link nella parte superiore della pagina. Inizieremo concentrandoci sul La mia scena
classe. Dentro MyScene.m
, troverai due metodi, initWithSize:
e touchesBegan: withEvent:
.
Nel initWithSize:
, rimuovere o commentare il codice relativo al file SKLabelNode
istanza in quanto non ne abbiamo bisogno in questo tutorial. Dai un'occhiata all'implementazione aggiornata di initWithSize:
sotto.
- (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;
Nel touchesBegan: withEvent:
, facciamo qualcosa di simile. Per ora, il metodo dovrebbe contenere solo la logica per il rilevamento del tocco e la posizione del tocco dell'utente. Queste modifiche ti daranno un avvertimento sul compilatore, ma ne elimineremo più avanti in questo tutorial.
- (void) touchesBegan: (NSSet *) tocca conEvent: (UIEvent *) event for (UITouch * tocco in tocco) posizione CGPoint = [touch locationInNode: self];
Il prossimo passo è creare due nuove classi. La prima classe, MenuScene
, sarà usato per il menu principale e la seconda classe, multiscene
, sarà usato per l'interfaccia multiplayer. Entrambe le classi sono sottoclassi di SKScene
. Il La mia scena
la classe verrà utilizzata per implementare l'interfaccia per giocatore singolo.
Come abbiamo visto nel La mia scena
classe, abbiamo bisogno di implementare un inizializzatore per ogni classe. Per ora, l'inizializzatore imposta solo il colore di sfondo della scena come abbiamo visto MyScene.m
. L'inizializzatore di MenuScene
la classe deve anche impostare il titolo del gioco. Per fare ciò, dobbiamo occuparci di alcune cose.
SKSpriteNode
oggetto.zPosition
.scala
.posizione
.Dai un'occhiata all'implementazione di initWithSize:
del MenuScene
classe per chiarimenti.
- (id) initWithSize: (CGSize) size self = [super initWithSize: size]; if (self) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) verde: (220.0 / 255.0) blu: (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;
Ora dovresti avere un menu principale e un titolo. È ora di aggiornare il controller della vista principale in modo che visualizzi il menu ogni volta che viene avviata l'applicazione. Aperto ViewController.m
, individuare il viewDidLoad
metodo e sostituire il SKScene
istanza con un'istanza di MenuScene
classe come mostrato di seguito.
- (void) viewDidLoad [super viewDidLoad]; // Configura la vista. SKView * skView = (SKView *) self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; // Crea e configura la scena. Scena SKScene = [MenuScene sceneWithSize: skView.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; // Presenta la scena. [skView presentScene: scene];
Non dimenticare di importare il file di intestazione del file MenuScene
classe.
#import "ViewController.h" #import "MenuScene.h"
Grande. È tempo di costruire il tuo progetto ed eseguirlo per verificare che tutto funzioni correttamente. Dovresti vedere un'interfaccia simile allo screenshot qui sotto.
Sfida: Per creare un'esperienza unica, ti sfidiamo a fare quanto segue.
MenuScene
oggetto del titolo.Prima di aggiungere oggetti al gioco, dobbiamo aggiungere la possibilità di navigare nel gioco. Dichiara due UIButton
istanze nel MenuScene
classe e una variabile, sizeGlobal
, di tipo CGSize
per memorizzare la dimensione dello schermo. Quest'ultimo ci aiuterà a posizionare gli oggetti sullo schermo. Aggiornare MenuScene.m
come mostrato di seguito.
#import "MenuScene.h" @interface MenuScene () CGSize sizeGlobal; UIButton * singlePlayerButton; UIButton * multiPlayerButton; @fine
Impostato sizeGlobal
a taglia
nell'inizializzatore della classe come mostrato nello snippet di codice seguente.
- (id) initWithSize: (CGSize) size self = [super initWithSize: size]; if (self) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) verde: (220.0 / 255.0) blu: (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;
Quindi, dichiarare tre metodi nel MenuScene
classe.
didMoveToView:
per presentare i pulsanti quando il gioco passa alla visualizzazione del menu.moveToSinglePlayerGame
quale transizioni il gioco al La mia scena
scena e rimuove i pulsanti.moveToMultiPlayerGame
quale transizioni il gioco al multiscene
scena e rimuove anche i pulsanti.Nel didMoveToView:
, l'applicazione verifica se la transizione di scena è avvenuta senza problemi. Se non si sono verificati problemi, l'applicazione carica le risorse, le visualizza all'utente e crea un'istanza dei pulsanti.
- (void) didMoveToView: (SKView *) view UIImage * buttonImageNormal = [UIImage imageNamed: @ "singleBtn.png"]; singlePlayerButton = [Pulsante UIButtonWithType: 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 = [Pulsante UIButtonWithType: 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];
Nel didMoveToView:
, Noi chiamiamo moveToSinglePlayerGame
e moveToMultiPlayerGame
. Implementiamo questi metodi successivamente. In ogni metodo, dobbiamo fare quanto segue.
La mia scena
o multiscene
.Puoi implementare questi metodi da solo? Se non sei sicuro, dai un'occhiata alle loro implementazioni di seguito.
- (vuoto) 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];
- (vuoto) 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];
Non dimenticare di aggiungere una dichiarazione di importazione per i file di intestazione di La mia scena
e multiscene
.
#import "MenuScene.h" #import "MyScene.h" #import "MultiScene.h" @interface MenuScene () CGSize sizeGlobal; UIButton * singlePlayerButton; UIButton * multiPlayerButton; @fine
Crea il tuo progetto ed esegui l'applicazione in iOS Simulator o su un dispositivo fisico. Il gioco dovrebbe ora assomigliare allo screenshot qui sotto.
Il menu principale è finito. È ora di concentrarsi sull'interfaccia per giocatore singolo del gioco (La mia scena
). Il La mia scena
la classe conterrà la maggior parte della logica del gioco. Il primo passo è posizionare i fiori che sparano proiettili nella parte inferiore dello schermo. Creeremo tre fiori, ognuno dei quali avrà proprietà uniche.
Traccia inoltre il numero di missili esplosi e mostra quel valore in un altro SKLabelNode
di nome labelMissilesExploded
. Come puoi vedere di seguito, avremo bisogno di un certo numero di variabili di istanza o ivar
S. Lo scopo di ogni ivar diventerà chiaro quando aggiorniamo il initWithSize:
metodo in La mia scena
.
#import "MyScene.h" @interface MyScene () CGSize sizeGlobal; SKLabelNode * labelflowerBullets1; SKLabelNode * labelflowerBullets2; SKLabelNode * labelflowerBullets3; SKLabelNode * labelMissilesExploded; posizione int; int monstersDead; int missileExploded; int flowerBullets1; int flowerBullets2; int flowerBullets3; @fine
Nel initWithSize:
, istanziamo e configuriamo i vari SKLabelNode
casi.
- (id) initWithSize: (CGSize) size if (self = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) verde: (220.0 / 255.0) blu: (54.0 / 255.0) alfa : 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: @ "Missili Esplosi:% 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 (posizione * 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 (posizione * 3-position / 2, labelflowerBullets3.frame.size.height / 2); labelflowerBullets3.zPosition = 3; [self addChild: labelflowerBullets3]; return self;
Nel initWithSize:
, anche noi chiamiamo addFlowerCommand
, che non abbiamo ancora coperto. L'implementazione non è difficile come puoi vedere qui sotto. Nel addFlowerCommand
, istanziamo tre SKSpriteNode
istanze, una per ciascun fiore e posizionale nella parte inferiore dello schermo con l'aiuto di posizione
.
- (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];
Ora puoi creare il progetto ed eseguirlo in iOS Simulator per vedere l'interfaccia per giocatore singolo del gioco.
Abbiamo fiori, ma abbiamo ancora bisogno di alcuni mostri. È ora di implementare il addMonstersBetweenSpace:
metodo. In questo metodo, creiamo tre mostri e li posizioniamo tra i fiori. La posizione dei mostri è determinata dal spaceOrder
variabile. Posizioniamo casualmente i mostri usando getRandomNumberBetween: a:
, che genera un numero casuale tra due numeri dati.
- (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];
L'implementazione di getRandomNumberBetween: a:
è mostrato sotto.
- (int) getRandomNumberBetween: (int) da a: (int) a return (int) da + arc4random ()% (a - from + 1);
Invochiamo addMonstersBetweenSpace:
due volte nel initWithSize:
metodo del La mia scena
classe.
- (id) initWithSize: (CGSize) size if (self = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) verde: (220.0 / 255.0) blu: (54.0 / 255.0) alfa : 1,0]; // ... // // Aggiungi mostri [self addMonstersBetweenSpace: 1]; [self addMonstersBetweenSpace: 2]; return self;
Ora che abbiamo fiori e mostri, è tempo di aggiungere i missili. Abbiamo bisogno di fare quanto segue per realizzare questo.
SKAction
invocare un metodo.SKAction
ripetere quell'azione.addMissilesFromSky:
, che genererà casualmente tre nuovi missili e li aggiungerà alla scena. Dichiareremo il SKAction
istanze in initWithSize:
. Dai un'occhiata all'implementazione aggiornata di initWithSize:
sotto.
- (id) initWithSize: (CGSize) size if (self = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: (198.0 / 255.0) verde: (220.0 / 255.0) blu: (54.0 / 255.0) alfa : 1,0]; // ... // // Crea azioni SKAction * wait = [SKAction waitForDuration: 2]; SKAction * createMissiles = [SKAction runBlock: ^ [self addMissilesFromSky: size]; ]; SKAction * updateMissiles = [sequenza di SKAction: @ [wait, createMissiles]]; [self runAction: [SKAction repeatActionForever: updateMissiles]]; return self;
L'implementazione di addMissilesFromSky:
è mostrato sotto.
- (void) addMissilesFromSky: (CGSize) size int numberMissiles = [self getRandomNumberBetween: 0 a: 3]; per (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];
Se costruisci ed esegui la tua applicazione, il risultato dovrebbe essere simile allo screenshot qui sotto.
Sfida: È grandioso, ma abbiamo davvero bisogno di più mostri. Ti sfidiamo a fare quanto segue.
Possiamo vedere alcuni movimenti, ma abbiamo bisogno della componente chiave del gioco, l'interazione dell'utente. Aggiungiamo l'interazione dell'utente sfruttando due metodi, touchesBegan: withEvent:
e positionOfWhichFlowerShouldBegin:
. Per aggiungere l'interazione dell'utente, dobbiamo tenere in considerazione quanto segue.
L'implementazione aggiornata di touchesBegan: withEvent:
è mostrato sotto.
- (void) touchesBegan: (NSSet *) tocca conEvent: (UIEvent *) event for (UITouch * tocco in tocco) posizione CGPoint = [touch locationInNode: self]; // Restituisce se l'utente tocca sotto un fiore se (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]];
Anche se questo è un sacco di codice da passare, non è così complicato. Controlla se ci sono dei proiettili rimasti per ogni fiore e rilevi la zona in cui l'utente ha toccato invocando positionOfWhichFlowerShouldBegin:
, di cui parleremo tra un momento. Allo stesso tempo, verifichiamo se l'utente ha toccato sotto il fiore, il che impedisce al fiore di sparare un proiettile.
se (location.y < 120) return;
Il positionOfWhichFlowerShouldBegin:
metodo restituisce la posizione che corrisponde a una zona specifica in cui l'utente ha toccato. Ricorda che hai diviso lo schermo in tre parti per posizionare i tre fiori, quindi dovrai rilevare la zona in cui l'utente ha toccato e collegarlo a uno dei fiori. Il fiore che spara al proiettile sarà quello più vicino al tocco dell'utente. Questo è ciò che l'implementazione di positionOfWhichFlowerShouldBegin:
sembra.
- (int) positionOfWhichFlowerShouldBegin: (int) numero posizione di ritorno * numero - posizione / 2;
Per far muovere i proiettili, dobbiamo crearne un altro SKSpriteNode
esempio. Ogni punto ha una durata e un SKAction
associato ad esso. Anche questa logica è inclusa touchesBegan: withEvent:
. Dai un'occhiata all'implementazione aggiornata di seguito.
- (void) touchesBegan: (NSSet *) tocca conEvent: (UIEvent *) event for (UITouch * tocco in tocco) posizione CGPoint = [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) durata: durata]; SKAction * remove = [SKAction removeFromParent]; [bullet runAction: [SKAction sequence: @ [move, remove]]]; [self addChild: bullet];
Se costruisci e esegui la tua applicazione, i fiori dovrebbero essere in grado di sparare proiettili. Non esplodono ancora, ma ci penseremo noi nel prossimo tutorial.
Sfida: Sei pronto per un'altra sfida? Dai un'occhiata a queste sfide.
Se hai seguito i passaggi di questo tutorial, ora dovresti avere le basi del gioco Missile Command usando il framework Sprite Kit. Se avete domande o commenti, sentitevi liberi di lasciare un commento qui sotto.