Build Missile Command avec Sprite Kit Configuration du projet

Dans ce didacticiel, vous apprendrez à utiliser le framework Sprite Kit d’Apple pour recréer un jeu Missile Command sur iPad. En cours de route, vous en apprendrez plus sur plusieurs concepts de base tels que, les sprites, les touchers, la physique, les collisions et les explosions. Le second didacticiel a pour but d’ajouter de la physique, des collisions et des explosions. Le deuxième tutoriel étend également l'expérience de jeu en ajoutant un mode multi-joueurs.


Souvenirs

Vous souvenez-vous de Missile Command? Atari a publié le jeu original le 8 mars 1981. Il s'agissait d'un jeu d'action conçu pour les systèmes Arcade et qui est devenu très populaire dans le monde entier..

Depuis sa sortie en 1981, plusieurs adaptations ont été apportées pour diverses plates-formes. Il est maintenant temps de recréer le jeu original à l'aide des technologies modernes, iOS, Objective-C et iPad..

Vous pouvez toujours jouer au jeu original. Jetez un coup d'œil sur IGN et revivez certains de vos souvenirs d'enfance.

Aperçu final

La capture d'écran ci-dessous vous donne une idée de ce à quoi ressemblera le résultat final. Si vous aimez ce que vous voyez, alors commençons.



Exigences

Pour compléter ce didacticiel, vous aurez besoin de Xcode 5 et du dernier SDK iOS 7. Vous pouvez télécharger Xcode 5 et le SDK à partir du centre de développement iOS..

À la fin de chaque section, vous trouverez un ou plusieurs défis. L'objectif de ces défis est de vous aider à apprendre les techniques et technologies utilisées dans ce tutoriel. Certaines sont faciles tandis que d'autres seront plus difficiles, nécessitant une bonne connaissance du cadre du kit Sprite. À l'exception du dernier défi, rappelez-vous que les tâches ne sont pas nécessaires pour terminer le didacticiel. Cependant, nous espérons que vous leur donnerez un essai.

Si vous avez des questions sur le cadre du kit Sprite, nous vous suggérons de consulter nos autres didacticiels sur le kit Sprite sur Mobiletuts.+.


1. Configuration du projet

Lancez Xcode 5 et créez un nouveau projet Sprite Kit en sélectionnant Nouveau> Projet… du Fichier menu. Choisir la Jeu SpriteKit modèle, nommez votre projet Commande de missiles, et sélectionnez iPad dans la liste Dispositifs menu.



Si vous avez des questions sur cette étape, nous vous encourageons à lire une explication plus détaillée de cette étape dans Construire un jeu d'avion avec le kit Sprite - Configuration du projet..

Une fois le projet configuré, ajoutez les ressources du projet, que vous pouvez télécharger en utilisant le lien en haut de la page. Nous allons commencer par nous concentrer sur la Ma scène classe. À l'intérieur MyScene.m, vous trouverez deux méthodes, initWithSize: et touchesBegan: withEvent:.

Dans initWithSize:, supprimer ou commenter le code qui est lié à la SKLabelNode exemple comme nous n'en avons pas besoin dans ce tutoriel. Jetez un coup d’œil à l’implémentation mise à jour de initWithSize: au dessous de.

- (id) initWithSize: (CGSize) taille self = [super initWithSize: size]; if (self) self.backgroundColor = [SKColor colorWithRed: 0,15 vert: 0,15 bleu: 0,3 alpha: 1,0];  retourner soi-même; 

Dans touchesBegan: withEvent:, nous faisons quelque chose de similaire. Pour l'instant, la méthode ne doit contenir que la logique de détection tactile et l'emplacement du toucher de l'utilisateur. Ces modifications vous donneront un avertissement pour le compilateur, mais nous nous en débarrasserons plus tard dans ce tutoriel..

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) événement pour (UITouch * touches tactiles) CGPoint location = [touch locationInNode: self]; 

Votre prochaine étape consiste à créer deux nouvelles classes. La première classe, MenuScene, sera utilisé pour le menu principal et la deuxième classe, MultiScene, sera utilisé pour l'interface multijoueur. Les deux classes sont des sous-classes de SKScene. le Ma scène la classe sera utilisée pour implémenter l'interface mono-joueur.

Comme nous l'avons vu dans le Ma scène classe, nous devons implémenter un initialiseur pour chaque classe. Pour l'instant, l'initialiseur ne définit que la couleur d'arrière-plan de la scène, comme nous l'avons vu dans MyScene.m. L'initialiseur du MenuScene La classe doit également définir le titre du jeu. Pour ce faire, nous devons nous occuper de quelques choses.

  • Créer un SKSpriteNode objet.
  • Définir sa zPosition.
  • Définir sa échelle.
  • Définir sa position.
  • Ajouter l'objet en tant qu'enfant à la classe.

Jetez un coup d’œil à la mise en œuvre de initWithSize: du MenuScene classe pour clarification.

- (id) initWithSize: (CGSize) taille self = [super initWithSize: size]; if (self) self.backgroundColor = [SKColor couleurWithRed: (198.0 / 255.0) vert: (220.0 / 255.0) bleu: (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); [auto addChild: titre];  retourner soi-même; 

Vous devriez maintenant avoir un menu principal et un titre. Il est temps de mettre à jour le contrôleur de vue principal afin qu'il affiche le menu à chaque lancement de l'application. Ouvrir ViewController.m, localiser le viewDidLoad méthode et remplacer le SKScene instance avec une instance du MenuScene classe comme ci-dessous.

- (void) viewDidLoad [super viewDidLoad]; // Configure la vue. SKView * skView = (SKView *) self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; // Crée et configure la scène. SKScene * scene = [MenuScene sceneWithSize: skView.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; // Présente la scène. [skView presentScene: scene]; 

N'oubliez pas d'importer le fichier d'en-tête du MenuScene classe.

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

Génial. Il est temps de construire votre projet et de l'exécuter pour vérifier que tout fonctionne correctement. Vous devriez voir une interface similaire à la capture d'écran ci-dessous.


Défi: Pour créer une expérience unique, nous vous mettons au défi de faire ce qui suit.

  • Modifier les couleurs de fond de chaque scène.
  • Jouez avec les propriétés du MenuScene objet titre.

2. Objets, fleurs, monstres et missiles

Avant d'ajouter des objets au jeu, nous devons ajouter la possibilité de naviguer dans le jeu. En déclarer deux UIButton cas dans le MenuScene classe et une variable, tailleGlobal, de type CGSize pour stocker la taille de l'écran. Ce dernier nous aidera à positionner les objets sur l’écran. Mettre à jour MenuScene.m comme indiqué ci-dessous.

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

Ensemble tailleGlobal à Taille dans l'initialiseur de la classe, comme indiqué dans l'extrait de code ci-dessous.

- (id) initWithSize: (CGSize) taille self = [super initWithSize: size]; if (self) self.backgroundColor = [SKColor couleurWithRed: (198.0 / 255.0) vert: (220.0 / 255.0) bleu: (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); [auto addChild: titre]; tailleGlobal = taille;  retourner soi-même; 

Ensuite, déclarez trois méthodes dans le MenuScene classe.

  • didMoveToView: Présenter les boutons lorsque le jeu passe à la vue du menu.
  • moveToSinglePlayerGame qui passe le jeu à la Ma scène scène et supprime les boutons.
  • moveToMultiPlayerGame qui passe le jeu à la MultiScene scène et supprime également les boutons.

Dans didMoveToView:, l'application vérifie si la transition de scène s'est déroulée sans problème. Si aucun problème n'est apparu, l'application charge les ressources, les affiche à l'utilisateur et instancie les boutons..

- (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: [WhiteColor UIColor] pourState: UIControlStateNormal]; UIImage * strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth: 12 topCapHeight: 0]; [singlePlayerButton setBackgroundImage: strechableButtonImageNormal forState: UIControlStateNormal]; [singlePlayerButton addTarget: action propre: @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] pourState: UIControlStateNormal]; UIImage * strechableButtonImageNormal2 = [buttonImageNormal2 stretchableImageWithLeftCapWidth: 12 topCapHeight: 0]; [multiPlayerButton setBackgroundImage: strechableButtonImageNormal2 forState: UIControlStateNormal]; [multiPlayerButton addTarget: action propre: @selector (moveToMultiPlayerGame) forControlEvents: UIControlEventTouchUpInside]; [self.view addSubview: multiPlayerButton]; 

Dans didMoveToView:, nous appelons moveToSinglePlayerGame et moveToMultiPlayerGame. Implémentons ces méthodes ensuite. Dans chaque méthode, nous devons faire ce qui suit.

  • Créer une instance de soit Ma scène ou MultiScene.
  • Créer une transition de scène.
  • Présenter la nouvelle scène.
  • Enlevez les boutons.

Pouvez-vous implémenter ces méthodes vous-même? Si vous n'êtes pas sûr, jetez un coup d'œil à leurs implémentations ci-dessous..

- (void) moveToSinglePlayerGame SKScene * scene = [MyScene sceneWithSize: self.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; SKTransition * transition = [SKTransitionveheWithDirection: SKTransitionDirectionLeft durée: 1]; SKView * skView = (SKView *) self.view; [skView presentScene: transition de scène: transition]; [singlePlayerButton removeFromSuperview]; [multiPlayerButton removeFromSuperview]; 
- (void) moveToMultiPlayerGame SKScene * scene = [Scène multiple avec scene: avec auto.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; SKTransition * transition = [SKTransitionveheWithDirection: SKTransitionDirectionLeft durée: 1]; SKView * skView = (SKView *) self.view; [skView presentScene: transition de scène: transition]; [singlePlayerButton removeFromSuperview]; [multiPlayerButton removeFromSuperview]; 

N'oubliez pas d'ajouter une instruction d'importation pour les fichiers d'en-tête de Ma scène et MultiScene.

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

Générez votre projet et exécutez l'application dans le simulateur iOS ou sur un périphérique physique. Le jeu devrait maintenant ressembler à la capture d'écran ci-dessous.


Le menu principal est terminé. Il est temps de se concentrer sur l'interface mono-joueur du jeu (Ma scène). le Ma scène La classe contiendra l'essentiel de la logique du jeu. La première étape consiste à positionner les fleurs tirant des balles au bas de l'écran. Nous allons créer trois fleurs, chacune ayant des propriétés uniques.

Vous pourrez également suivre le nombre de missiles explosés et afficher cette valeur dans un autre SKLabelNode nommé labelMissilesExploded. Comme vous pouvez le voir ci-dessous, nous aurons besoin d'un certain nombre de variables d'instance ou Ivars. Le but de chaque ivar deviendra clair lorsque nous mettrons à jour le initWithSize: méthode en Ma scène.

#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;  @fin

Dans initWithSize:, nous instancions et configurons les différents SKLabelNode les instances.

- (id) initWithSize: (CGSize) taille if (self = [super initWithSize: size]) self.backgroundColor = [SKColor couleurWithRed: (198.0 / 255.0) vert: (220.0 / 255.0) bleu: (54.0 / 255.0) alpha : 1,0]; position = size.width / 3; tailleGlobal = taille; [auto addFlowerCommand]; // Étiquette indiquant les missiles explosés labelMissilesExploded = [SKLabelNode labelNodeWithFontNamed: @ "Hiragino-Kaku-Gothic-ProN"]; labelMissilesExploded.text = [NSString stringWithFormat: @ "Missiles explosés:% d", missileExploded]; labelMissilesExploded.fontSize = 30; labelMissilesExploded.position = CGPointMake (size.width / 2, size.height-labelMissilesExploded.frame.size.height); labelMissilesExploded.zPosition = 3; [auto 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; [auto 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; [auto 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; [auto addChild: labelflowerBullets3];  retourner soi-même; 

Dans initWithSize:, nous appelons aussi addFlowerCommand, que nous n'avons pas encore couverts. La mise en œuvre n'est pas difficile comme vous pouvez le voir ci-dessous. Dans addFlowerCommand, nous instancions trois SKSpriteNode cas, un pour chaque fleur, et placez-les au bas de l'écran à l'aide de position.

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

Vous pouvez maintenant construire le projet et l'exécuter dans le simulateur iOS pour afficher l'interface solo du jeu..

Nous avons des fleurs, mais nous avons encore besoin de monstres. Il est temps de mettre en œuvre le addMonstersBetweenSpace: méthode. Dans cette méthode, nous créons trois monstres et les positionnons entre les fleurs. La position des monstres est déterminée par le spaceOrder variable. Nous positionnons les monstres au hasard en utilisant getRandomNumberBetween: to:, qui génère un nombre aléatoire entre deux nombres donnés.

- (void) addMonstersBetweenSpace: (int) spaceOrder pour (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'implémentation de getRandomNumberBetween: to: est montré ci-dessous.

- (int) getRandomNumberBetween: (int) de to: (int) to return (int) de + arc4random ()% (to - from + 1); 

Nous invoquons addMonstersBetweenSpace: deux fois dans le initWithSize: méthode du Ma scène classe.

- (id) initWithSize: (CGSize) taille if (self = [super initWithSize: size]) self.backgroundColor = [SKColor couleurWithRed: (198.0 / 255.0) vert: (220.0 / 255.0) bleu: (54.0 / 255.0) alpha : 1,0]; //… // // Ajouter des monstres [auto addMonstersBetweenSpace: 1]; [auto addMonstersBetweenSpace: 2];  retourner soi-même; 

Maintenant que nous avons des fleurs et des monstres, il est temps d'ajouter les missiles. Nous devons faire ce qui suit pour accomplir cela.

  • Créé un SKAction invoquer une méthode.
  • Créé un SKAction répéter cette action.
  • Mettre en place addMissilesFromSky:, qui va générer au hasard trois nouveaux missiles et les ajouter à la scène.

Nous allons déclarer le SKAction cas dans initWithSize:. Jetez un coup d’œil à l’implémentation mise à jour de initWithSize: au dessous de.

- (id) initWithSize: (CGSize) taille if (self = [super initWithSize: size]) self.backgroundColor = [SKColor couleurWithRed: (198.0 / 255.0) vert: (220.0 / 255.0) bleu: (54.0 / 255.0) alpha : 1,0]; //… // // Créer des actions SKAction * wait = [SKAction waitForDuration: 2]; SKAction * createMissiles = [SKAction runBlock: ^ [self addMissilesFromSky: size]; ]; SKAction * updateMissiles = [Séquence SKAction: @ [wait, createMissiles]]; [self runAction: [SKAction repeatActionForever: updateMissiles]];  retourner soi-même; 

L'implémentation de addMissilesFromSky: est montré ci-dessous.

- (void) addMissilesFromSky: (CGSize) taille int numberMissiles = [self getRandomNumberBetween: 0 to: 3]; pour (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];  

Si vous construisez et exécutez votre application, le résultat devrait ressembler à la capture d'écran ci-dessous..


Défi: C'est génial, mais nous avons vraiment besoin de plus de monstres. Nous vous mettons au défi de faire ce qui suit.

  • Ajouter plus de monstres.
  • Ajouter plus de fleurs.
  • Modifier le mouvement des missiles.

3. Interaction utilisateur

Nous pouvons voir un certain mouvement, mais nous avons besoin du composant clé du jeu, l’interaction de l’utilisateur. Nous ajoutons l'interaction utilisateur en utilisant deux méthodes, touchesBegan: withEvent: et positionOfWichichflowerShouldBambin:. Pour ajouter une interaction utilisateur, nous devons prendre en compte les éléments suivants.

  • Chaque fleur ne peut tirer que dix balles.
  • Vous devez détecter l'emplacement du contact de l'utilisateur et utiliser la fleur la plus proche pour tirer la balle..
  • La balle devrait se déplacer à l'endroit du contact de l'utilisateur.
  • La balle devrait exploser à l'endroit du contact de l'utilisateur.

La mise à jour de la mise en œuvre de touchesBegan: withEvent: est montré ci-dessous.

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) événement pour (UITouch * touches tactiles) CGPoint location = [touch locationInNode: self]; // Retour si l'utilisateur tape sous une fleur 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 = [position propre de quelfluxfleurschoitait: 2];  else if (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [position propre de quelfleursfleur devrait commencer: 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 = [position de soi-mêmeDeFlowerShouldBegin: 1];  else if (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [position propre de quelfleursfleur devrait commencer: 3];  else return;  else if (flowerBullets3> 0) flowerBullets3--; [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; bulletBeginning = [position propre de quelfleursfleur devrait commencer: 3];  else if (flowerBullets1> 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString stringWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [position de soi-mêmeDeFlowerShouldBegin: 1];  else return;  [labelflowerBullets2 setText: [NSString stringWithFormat: @ "% d", flowerBullets2]];  else bulletBeginning = position * 3-position / 2; si (flowerBullets3> 0) flowerBullets3--; else if (flowerBullets3 == 0 && flowerBullets2> 0) flowerBullets2--; [labelflowerBullets2 setText: [NSString stringWithFormat: @ "% d", flowerBullets2]]; bulletBeginning = [position propre de quelfluxfleurschoitait: 2];  else if (flowerBullets1> 0) flowerBullets1--; [labelflowerBullets1 setText: [NSString stringWithFormat: @ "% d", flowerBullets1]]; bulletBeginning = [position de soi-mêmeDeFlowerShouldBegin: 1];  else return;  [labelflowerBullets3 setText: [NSString stringWithFormat: @ "% d", flowerBullets3]]; 

Même si cela fait beaucoup de code, ce n'est pas si compliqué. Vous vérifiez s'il reste des puces pour chaque fleur et détectez la zone dans laquelle l'utilisateur a tapé en appelant positionOfWichichflowerShouldBambin:, dont nous discuterons dans un instant. Dans le même temps, nous vérifions si l'utilisateur a tapé sous la fleur, ce qui l'empêche de tirer une balle.

si (location.y < 120) return;

le positionOfWichichflowerShouldBambin: La méthode retourne la position qui correspond à une zone spécifique dans laquelle l'utilisateur a tapé. N'oubliez pas que vous avez divisé l'écran en trois parties pour positionner les trois fleurs. Vous devez donc détecter la zone dans laquelle l'utilisateur a tapé et la lier à l'une des fleurs. La fleur qui tire la balle sera celle la plus proche du robinet de l'utilisateur. C’est ce que la mise en œuvre de positionOfWichichflowerShouldBambin: ressemble à.

- (int) positionFichierFlowerShouldBegin: (int) numéro position de retour * numéro - position / 2; 

Pour faire bouger les balles, nous devons créer un autre SKSpriteNode exemple. Chaque balle a une durée et une SKAction associé avec. Cette logique est également incluse dans touchesBegan: withEvent:. Regardez l'implémentation mise à jour ci-dessous.

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) événement pour (UITouch * touches tactiles) 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; durée de flottement = (2 * location.y) /sizeGlobal.width; SKAction * move = [SKAction moveTo: CGPointMake (location.x, location.y) durée: durée]; SKAction * remove = [SKAction removeFromParent]; [bullet runAction: [séquence SKAction: @ [déplacer, supprimer]]]; [auto addChild: bullet]; 

Si vous construisez et exécutez votre application, les fleurs devraient pouvoir tirer des balles. Ils n'explosent pas encore, mais nous nous en occuperons dans le prochain tutoriel..


Défi: Êtes-vous prêt pour un autre défi? Jetez un coup d'œil à ces défis.

  • Créer et définir différents mouvements de balle.
  • Modifier la durée du mouvement de chaque balle.

Conclusion

Si vous avez suivi les étapes de ce didacticiel, vous devriez maintenant disposer des bases du jeu Missile Command utilisant le framework Sprite Kit. Si vous avez des questions ou des commentaires, n'hésitez pas à laisser un commentaire ci-dessous.