iOS SDK Créer un jeu de faits - Création d'interface

Ce tutoriel va vous apprendre à utiliser le framework Sprite Kit pour créer un jeu de faits basé sur des questions. Il est conçu pour les utilisateurs novices et avancés. En cours de route, vous appliquerez le noyau du kit Sprite. Les didacticiels du jeu de faits sont divisés en trois parties afin de couvrir complètement chaque section. Après ce didacticiel en trois parties, les lecteurs pourront créer un simple jeu de questions / réponses comportant des sons, des animations, des menus, des règles, des minuteries et une interaction UIKit..


introduction

Cette série est divisée en trois parties: Configuration du projet, Création d'interface et Logique de jeu. Chaque partie produira un résultat pratique et la somme de toutes les parties produira le jeu final. Bien que chaque partie puisse être lue indépendamment, pour une meilleure compréhension et orientation, nous suggérons que le tutoriel soit suivi pas à pas. Nous avons également inclus le code source de chaque partie séparément. Ainsi, fournir un moyen de démarrer le tutoriel dans n’importe quelle partie de la série.

Ceci est la deuxième partie de notre série de didacticiels Jeu de faits avec Sprite Kit. Dans ce tutoriel, vous allez programmer la sélection de niveau et l’interface principale de la scène de jeu. Ce tutoriel se concentre sur plusieurs aspects tels que, la personnalisation UITableView, initialiseurs de classes personnalisées, listes de propriétés et SKActions. Nous expliquerons tout plus loin ci-dessous. Si vous n'avez pas encore terminé la première partie de la série, vous pouvez télécharger le projet et le ramasser exactement à l'endroit où nous nous sommes arrêtés..

Voici à quoi ressemblera notre résultat final:


Illustration du résultat final - Faits

1. Sélection du niveau

Étape 1

L'objectif principal de ce jeu est de créer plusieurs questions divisées par plusieurs niveaux. De cette façon, vous devez créer une interface personnalisée pour choisir le niveau auquel vous voulez jouer. Pour ce faire, vous devez ajouter un autre Objectif c classe (Fichier -> Nouveau -> Fichier). Nomme le LevelSelect et choisissez le SKScene comme la superclasse. Vous verrez deux nouveaux fichiers dans votre projet.

Pour la sélection du niveau, vous utiliserez le UITableView visualisez-le et configurez-le avec plusieurs propriétés. En outre, vous devez également nommer les niveaux et leurs descriptions. dans le LevelSelect.h vous devriez ajouter ces propriétés. L'extrait suivant vous aidera:

 @property (nonatomic, keep) UIButton * backButton; @property (keep, nonatomic) IBOutlet UITableView * tableView; @property (strong, nonatomic) NSArray * levelsArray; @property (strong, nonatomic) NSArray * levelsDescriptionArray;

L'extrait contient également un UIButton appelé backButton. A ce moment, le bouton est explicite. il aide l'utilisateur à revenir de l'interface de sélection de niveau à l'interface principale.

Étape 2

Ensuite, concentrez-vous sur LevelSelect.m. La première étape consiste à ajouter le -(id) initWithSize: taille (CGSize) méthode. Dans cette classe, vous ne configurerez que la couleur d'arrière-plan. Vous pouvez choisir la couleur que vous aimez le plus.

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

Depuis que vous utilisez UIKit vues, vous devez ajouter le -(void) didMoveToView: (SKView *) voir méthode. Cette méthode définit et configure le backButton et le tableView, place un libellé de titre pour la vue, alloue et initialise le levelsArray et le levelsDescriptionArray et ajoute le tableView à la vue principale. le bouton de retour peut être configuré comme suit:

 _backButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; _backButton.frame = CGRectMake (CGRectGetMidX (self.frame) -100, CGRectGetMaxY (self.frame) -100, 200, 70.0); _backButton.backgroundColor = [UIColor clearColor]; [_backButton setTitleColor: [WhiteColor UIColor] pourState: UIControlStateNormal]; UIImage * buttonExitImageNormal = [UIImage imageNamed: @ "back.png"]; UIImage * strechableButtonExitImageNormal = [buttonExitImageNormal stretchableImageWithLeftCapWidth: 12 topCapHeight: 0]; [_backButton setBackgroundImage: strechableButtonExitImageNormal forState: UIControlStateNormal]; [_backButton addTarget: action propre: @selector (moveToHome) forControlEvents: UIControlEventTouchUpInside]; [self.view addSubview: _backButton];

De plus, vous devez créer le moveToHomeméthode et importation la MyScene.h.

 -(void) moveToHome MyScene * myScene = [[MyScene alloc] initWithSize: CGSizeMake (CGRectGetMaxX (self.frame), CGRectGetMaxY (self.frame))]; [auto removeUIViews]; [self.scene.view presentScene: myScene]; 

Puisque vous devez enlever UIKIt vues à plus d'un endroit, créons une méthode qui fait exactement cela. La méthode s'appelle supprimerUIViews et est montré ci-dessous:

 -(void) removeUIViews [_backButton removeFromSuperview]; [_tableView removeFromSuperview]; 

Le libellé de cette interface est très simple. Essayez de le programmer vous-même. Si vous avez des problèmes, l'extrait suivant vous aidera.

 SKLabelNode * titleLabel = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; titleLabel.text = @ "Sélection du niveau !!"; titleLabel.fontSize = 60; titleLabel.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMidY (self.frame) +300); [auto addChild: titleLabel];

Étape 3

le tableView la configuration est un peu délicate car nous devons configurer plusieurs propriétés, telles que la taille et l'emplacement du cadre, la source de données et un délégué.

 _tableView = [[UITableView alloc] initWithFrame: CGRectMake (CGRectGetMidX (self.frame) -150, CGRectGetMidY (self.frame) -250, 300, 400)]; _tableView.dataSource = self; _tableView.delegate = self;

Les deuxième et troisième lignes de l'extrait de code susmentionné nécessitent une étape supplémentaire, car vous définissez simultanément deux vues. La source de données du UITableView est auto-défini et le UITableView a un délégué d'action. Dans LevelSelect.h vous devriez prolonger votre classe avec UITableViewDataSource et UITableViewDelegate. Votre LevelSelect.h devrait ressembler à:

 @interface LevelSelect: SKScene < UITableViewDataSource, UITableViewDelegate >

Puisque vous prolongez le UITableViewDataSource et UITableViewDelegate, des méthodes supplémentaires doivent être mises en œuvre, à savoir:

  1. -(NSInteger) tableView: (UITableView *) table numéro de sectionOfRowsInSection: (NSInteger) section
  2. -(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath

Le premier sert uniquement à connaître en temps réel le nombre de lignes existant dans la vue tableau. La seconde méthode est complexe car elle permet de renseigner et de configurer la vue tableau. La configuration de la vue table couvre le titre, la description et une image de ligne. Pour utiliser la description dans chaque ligne, nous devons initialiser chaque cellule avec le UITableViewCellStyleSubtitle style de cellule.

Cette méthode est responsable d’une étape supplémentaire: elle vérifie le niveau du joueur actuel et désactive les niveaux en avant de la actualPlayerLevel. La déclaration complète des méthodes est visible ci-dessous:

 -(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath NSString * levels = [_levelsArray objectAtIndex: indexPath.row]; NSString * descriptions = [_levelsDescriptionArray objectAtIndex: indexPath.row]; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: @ "identificateur"]; if (cell == nil) cell = [[UITableViewCell alloc]] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: @ "Identificateur"];  if (indexPath.row> = actualPlayerLevel) [cellule setUserInteractionEnabled: FALSE]; [cell.textLabel setText: levels]; cell.imageView.image = [UIImage imageNamed: @ "appleLogo.png"]; [cell.detailTextLabel setText: descriptions]; cellule de retour; 
 -(NSInteger) tableView: (UITableView *) numéro de la table (numéro de la vue): (NSInteger) section return [_levelsArray count]; 

Voici deux notes concernant la -(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath méthode. Vous n'avez pas encore initialisé les propriétés levelsArray, levelsDescriptionArray et actualPlayerLevel. Tout sera défini dans le -(void) didMoveToView: (SKView *) voir méthode. N'oubliez pas d'ajouter le actualPlayerLevel propriété à votre classe:

 @implementation LevelSelect long actualPlayerLevel; 

Étape 4

le niveauxArray est défini avec les noms des niveaux. Vous pouvez l'appeler "Niveau 1", "Niveau 2" ou tout autre nom de votre choix. le niveauxDescriptionArray suit le même principe, il s'agit d'une description pour chaque niveau et peut être défini avec les noms de votre choix. Une implémentation possible est:

 _levelsArray = [[NSArray alloc] initWithObjects: @ "niveau 1.", @ "niveau 2.", @ "niveau 3.", @ "niveau 4", @ "niveau 5", @ "niveau 6". , @ "Niveau 7.", @ "Niveau 8.", @ "Niveau 9.", Nul]; _levelsDescriptionArray = [[NSArray alloc] initWithObjects: @ "L'aventure commence.", @ "Une nouvelle étape.", @ "Réalisations?!", @ "Description du niveau 4", @ "Description du niveau 5", @ "Niveau 6 description ", @" description du niveau 7 ", @" description du niveau 8 ", @" description du niveau 9 ", nil];

Finalement, le actualPlayerLevel est un longue type de valeur qui représente le niveau du joueur. Pour le moment, disons que le niveau actuel est 1.

 actualPlayerLevel = 1;

le -(void) didMoveToView: (SKView *) voir méthode se termine lorsque vous ajoutez la vue tabulaire à l'écran:

 [self.view addSubview: _tableView];

Enfin, vous avez besoin d’un changement supplémentaire dans la MyScene.m -(void) moveToGame méthode. Vous devez appeler cette nouvelle classe à la place de l'ancienne. Cela peut être facilement réalisé par:

 -(void) moveToGame LevelSelect * factsScene = [[LevelSelect alloc]] initWithSize: CGSizeMake (CGRectGetMaxX (self.frame), CGRectGetMaxY (self.frame))]; // Même code //…

À ce stade, vous devriez Courir le projet et tester la nouvelle interface. Vous devriez voir quelque chose de similaire à l'image suivante:

Illustration de l'écran de sélection de niveau

2. Interface des faits

Étape 1

L'interface des faits est l'endroit où se produit l'action réelle. L'interface comporte plusieurs vues qui se traduisent directement en propriétés, telles que le nombre de vies restantes, le niveau actuel, une minuterie et les boutons true et false. De plus, pour cette classe, vous allez créer un initialiseur personnalisé. L'avantage de cet initialiseur personnalisé est que nous pouvons progresser dans le jeu et les valeurs relatives au niveau. De plus, les vies sont transmises à la classe et celle-ci réagit (analyse les données) en conséquence..

Encore une fois, nous allons utiliser SKLabelNode, UIButtons, et un NSMutableArray. Le complet FactsScene.h est le suivant:

 @interface FactsScene: SKScene NSMutableArray * heartArray;  @property (nonatomic, faible) SKLabelNode * currentLevelLabel; @property (nonatomic, faible) SKLabelNode * timerLevel; @property (nonatomic, keep) UIButton * trueButton; @property (nonatomic, keep) UIButton * falseButton; - (id) initWithSize: (CGSize) size inLevel: (NSInteger) niveau avecPlayerLives: (int) lives;

Il est maintenant temps de passer à la FactsScene.m et implémenter quelques objets. Vous avez besoin d'objets supplémentaires pour récupérer et stocker les données reçues par l'initialiseur. De plus, vous devez enregistrer le temps maximum qu'un joueur a pour répondre à chaque question. Modifier le fichier d'implémentation en conséquence.

 @implementation FactsScene NSUserDefaults * defaults; NSString * musicPath; NSInteger playerLives; NSInteger playerLevel; int maximumTime; 

Maintenant, vous devez écrire l'initialiseur et stocker ses valeurs. L'initialiseur personnalisé est défini comme un initialiseur normal et a la même structure. Cependant, il a plus de propriétés en tant que paramètres. Ça devrait ressembler à ça:

 -(id) initWithSize: (CGSize) size inLevel: (NSInteger) niveau avecPlayerLives: (int) lives if (self = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: 0.35 vert: 0.25 vert: 0.25 bleu: 0.5 alpha : 1,0]; defaults = [NSUserDefaults standardUserDefaults]; playerLives = vies; playerLevel = level; maximumTime = 30;  retourner soi-même; 

Étape 2

Pour l'instant, le durée maximale est 30 secondes, mais à l'avenir, la valeur passera à 60 secondes (ou à tout autre moment de votre choix). Maintenant dans le -(void) didMoveToView: (SKView *) voir ajoutez une image d'arrière-plan, une image avant, la vie du joueur, une minuterie, des boutons Vrai et Faux, et les questions du niveau actuel et total Pour le Contexte et de face image le code est simple et vous devriez pouvoir le faire facilement (en utilisant SKSpriteNode).

 SKSpriteNode * background = [SKSpriteNode spriteNodeWithImageNamed: @ "background.png"]; background.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMidY (self.frame)); background.size = CGSizeMake (768, 1024); [auto addChild: background]; SKSpriteNode * frontImage = [SKSpriteNode spriteNodeWithImageNamed: @ "transparentCenterBorder.png"]; frontImage.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMidY (self.frame)); frontImage.size = CGSizeMake (600, 450); [auto addChild: frontImage];

Les vies du joueur sont représentées avec une image de coeur. Puisque tu vas déclarer trois vies, tu dois mettre trois coeurs à l'écran. Vous utiliserez également un NSMutableArray puisque nous devons modifier sa taille de manière dynamique. L'extrait suivant vous aidera:

 heartArray = [[NSMutableArray alloc] init]; pour (NSInteger i = 0; i < playerLives; i++) SKSpriteNode* liveImage = [SKSpriteNode spriteNodeWithImageNamed:@"hearth.png"]; liveImage.scale = .6; liveImage.position = CGPointMake(CGRectGetMaxX(self.frame)-40-(i*50),CGRectGetMaxY(self.frame)-40); [heartArray insertObject:liveImage atIndex:i]; [self addChild:liveImage]; 

Les boutons true et false sont configurés comme suit:

 _trueButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; _trueButton.frame = CGRectMake (CGRectGetMidX (self.frame) -350, CGRectGetMidY (self.frame) +300, 335, 106); _trueButton.backgroundColor = [UIColor clearColor]; [_trueButton setTitleColor: [WhiteColor UIColor] pourState: UIControlStateNormal]; UIImage * buttonTrueImageNormal = [UIImage imageNamed: @ "trueBtn.png"]; UIImage * strechableButtonTrueImageNormal = [buttonTrueImageNormal stretchableImageWithLeftCapWidth: 12 topCapHeight: 0]; [_trueButton setBackgroundImage: strechableButtonTrueImageNormal forState: UIControlStateNormal]; [_trueButton addTarget: action propre: @selector (touchWillProduceASound) forControlEvents: UIControlEventTouchUpInside]; [self.view addSubview: _trueButton]; _falseButton = [UIButton buttonWithType: UIButtonTypeRoundedRect]; _falseButton.frame = CGRectMake (CGRectGetMidX (self.frame) +10, CGRectGetMidY (self.frame) +300, 335, 106); _falseButton.backgroundColor = [UIColor clearColor]; [_falseButton setTitleColor: [UIColor whiteColor] pourState: UIControlStateNormal]; UIImage * buttonFalseImageNormal = [UIImage imageNamed: @ "falseBtn.png"]; UIImage * strechableButtonFalseImageNormal = [buttonFalseImageNormal stretchableImageWithLeftCapWidth: 12 topCapHeight: 0]; [_falseButton setBackgroundImage: strechableButtonFalseImageNormal forState: UIControlStateNormal]; [_falseButton addTarget: action propre: @selector (touchWillProduceASound) forControlEvents: UIControlEventTouchUpInside]; [self.view addSubview: _falseButton];

Notez que les deux boutons appellent le touchWillProduceASound méthode. Cette méthode teste si une réponse donnée est correcte ou incorrecte. Dans cette partie, nous n'utilisons qu'un seul événement sonore (le faux).

 -(void) touchWillProduceASound long soundFlag = [defaults integerForKey: @ "sound"]; NSString * answer = @ "False"; if (soundFlag == 1) SKAction * sound; if ([answer isEqualToString: @ "False"]) sound = [SKAction playSoundFileNamed: @ "wrong.mp3" waitForCompletion: YES]; NSLog (@ "inside");  [self runAction: sound]; 

Étape 3

Le chronomètre est un SKLabelNode cela change à chaque seconde. Cependant, son initialisation se fait comme un simple SKLabelNode:

 _timerLevel = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; _timerLevel.text = @ "30"; _timerLevel.fontSize = 70; _timerLevel.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMidY (self.frame) +350); [auto addChild: _timerLevel];

Pour mettre à jour l’étiquette, vous devez créer un SKAction qui définit une minuterie personnalisée pour appeler une méthode personnalisée. Ensuite, nous devons créer un SKAction séquence:

 SKAction * wait = [SKAction waitForDuration: 1]; SKAction * updateTimer = [SKAction runBlock: ^ [self updateTimer]; ]; SKAction * updateTimerS = [séquence SKAction: @ [wait, updateTimer]]; [self runAction: [SKAction repeatActionForever: updateTimerS]];

Vous verrez un avertissement concernant la - (void) updateTimer méthode parce que vous ne l'avez pas encore créé. Cette méthode effectue plusieurs actions simultanément en prenant en compte plusieurs propriétés:

  • Vérifie si le son est activé
  • Met à jour le durée maximale property et Label, diminuant d'une valeur chaque seconde
  • Vérifie le durée maximale, et si la valeur est zéro, cela mettra fin au jeu ou changera pour une autre question (plus à ce sujet dans le prochain tutoriel)

Nous vous conseillons d'essayer d'écrire la méthode en utilisant le pseudo-code susmentionné. Mais si vous avez des problèmes, la méthode complète est présentée ci-dessous:

 - (void) updateTimer maximumTime--; if (maximumTime == 0) long soundFlag = [défaut par défaut integerForKey: @ "sound"]; if (soundFlag == 1) SKAction * sound; sound = [SKAction playSoundFileNamed: @ "beep.mp3" waitForCompletion: YES]; [self runAction: sound];  if (playerLives < 1) SKTransition* transition = [SKTransition fadeWithDuration:2]; MyScene* myscene = [[MyScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))]; [self removeUIViews]; [self.scene.view presentScene:myscene transition:transition];  else // other   [_timerLevel setText:[[NSNumber numberWithInt:maximumTime] stringValue]]; 

Étape 4

Une autre méthode manque, la supprimerUIViews. Ça enlève le UIKit vues de la vue quand une transition se produit.

 -(void) removeUIViews [_trueButton removeFromSuperview]; [_falseButton removeFromSuperview]; 

Il est maintenant temps de Courir le projet et voir l'écran des faits!

Illustration de l'écran des faits

3. Listes de propriétés

Il est maintenant temps d'ajouter des données à l'application. Aller à Fichier -> Nouveau -> Fichier et choisissez le fichier Property List (plist). Nommez-le "LevelDescription" et configurez-le comme suit:

Illustration de la liste de propriétés

Afin d'éviter de mettre toutes les données dans le fichier plist, vous pouvez télécharger le fichier directement sur le fichier zip (début de la page). Ce tutoriel ne couvre pas en profondeur l'analyse des données. Par conséquent, pour analyser ce fichier, l'extrait de code suivant est utilisé. Si vous avez des doutes, utilisez la zone de commentaire au bas de la page..

 NSString * plistPath = [[NSBundle mainBundle] pathForResource: @ "LevelDescription" ofType: @ "plist"]; NSMutableDictionary * dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile: plistPath]; if ([dictionnaire objectForKey: @ "Questions"]! = nil) NSMutableArray * array = [dictionnaire objectForKey: @ "Questions"]; pour (int i = 0; i < [array count]; i++) NSMutableDictionary *questions = [array objectAtIndex:i]; NSLog(@"ID %@", [questions objectForKey:@"id"]); NSLog(@"%@", [questions objectForKey:@"statement"]); NSLog(@"%@", [questions objectForKey:@"isCorrect"]); NSLog(@"%@", [questions objectForKey:@"additionalInfo"]);  

À présent, Courir le projet et observez les journaux de la console lorsque vous accédez à la vue Faits. Notez que le fichier plist peut être configuré de différentes manières. Si vous voulez, vous pouvez changer le dictionnaire, Tableau types et configurations. Notez que les modifications doivent être déclarées dans le cycle d'analyse. Nous vous conseillons vivement de jouer un peu avec le fichier plists et l’analyse de données inhérente.


Conclusion

À ce stade, vous devriez pouvoir utiliser et configurer un UITableView, interagir entre les frameworks SpriteKit et UIKit, créer SKTransitions et SKActions et créer et analyser des fichiers de propriétés. Dans la dernière section de cette série, vous découvrirez Game Logic..