SpriteKit From Scratch Contraintes et Actions

introduction

Dans ce tutoriel, le deuxième volet de la série SpriteKit From Scratch, vous en apprendrez sur les contraintes et les actions. Ces fonctionnalités permettent d’ajouter facilement du mouvement et des animations à votre jeu SpriteKit tout en limitant la position et l’orientation des nœuds du jeu..

Pour continuer avec moi, vous pouvez utiliser le projet que vous avez créé dans le premier tutoriel de cette série ou télécharger une nouvelle copie à partir de GitHub..

Les graphiques utilisés pour le jeu dans cette série sont disponibles sur GraphicRiver. GraphicRiver est une excellente source pour trouver des illustrations et des graphiques pour vos jeux..

1. Classes de nœuds et de scènes personnalisées

Avant de pouvoir ajouter des contraintes et des actions à une scène, nous devons d’abord créer quelques classes afin de pouvoir utiliser nos nœuds dans le code. Créer une nouvelle classe, PlayerNode, basé sur iOS> Source> Cocoa Touch Class modèle et assurez-vous qu'il s'agit d'une sous-classe de SKSpriteNode.

Si Xcode génère une erreur après la création de la classe, ajoutez une instruction d'importation pour le framework SpriteKit sous le importer UIKit déclaration:

importer UIKit importer SpriteKit

Ensuite, déclarez les trois propriétés suivantes dans le PlayerNode classe. Ces propriétés vont contenir les contraintes utilisées pour limiter le mouvement horizontal de la voiture.

import UIKit import SpriteKit class PlayerNode: SKSpriteNode var leftConstraint: SKConstraint! var middleConstraint: SKConstraint! var rightConstraint: SKConstraint! 

Créer un autre Cacao Touch Class et nommez-le MainScene, en faisant une sous-classe de SKScene.

En haut, ajoutez une déclaration d'importation pour le framework SpriteKit.

importer UIKit importer SpriteKit

Avec ces classes créées, ouvrez MainScene.sks, cliquez sur le fond gris pour sélectionner la scène, ouvrez le Inspecteur de classe personnalisé à droite, et mis Classe personnalisée à MainScene.

Sélectionnez la voiture et réglez sa classe sur PlayerNode de la même manière que vous l'avez fait pour la scène. Enfin, avec la voiture toujours sélectionnée, ouvrez le Inspecteur d'attributs et changer prénom à Joueur.

Maintenant que les classes de base sont configurées, nous pouvons commencer à créer des contraintes dans le code.

2. Contraintes

Contraintes dans SpriteKit, représenté par le SKConstraint classe, sont utilisés pour limiter la position et l’orientation de nœuds particuliers. Une grande variété de possibilités peut être obtenue avec des contraintes car elles peuvent être relatives à la scène ou à d’autres nœuds. Les contraintes fonctionnent également avec des plages de valeurs en plus des valeurs constantes afin que les sprites de votre scène puissent être fixés à un emplacement spécifique ou autorisés à se déplacer dans une zone donnée..

Les contraintes que nous allons ajouter sont les trois que nous avons déclarées dans le PlayerNode classe. Ces contraintes seront utilisées pour verrouiller la voiture sur les trois voies du jeu..

Ouvrir MainScene.swift et créer une propriété pour le joueur de type PlayerNode!. Cette propriété stockera une référence au noeud du joueur..

import UIKit import SpriteKit class MainScene: SKScene var player: PlayerNode! 

Ensuite, nous substituons la didMoveToView (_ :) méthode du MainScene classe:

écrasez func didMoveToView (view: SKView) super.didMoveToView (view) size = view.frame.size si let foundPlayer = childNodeWithName ("Player") as? PlayerNode player = foundPlayer let center = size.width / 2.0, difference = CGFloat (70.0) player.leftConstraint = SKConstraint.positionX (SKRange (constanteValue: centre - difference)) player.middleConstraint = SKConstraint.positionX (SKRon (constanteValue: constante). center)) player.rightConstraint = SKConstraint.positionX (SKRange (constanteValue: centre + différence)) player.leftConstraint.enabled = false player.rightConstraint.enabled = false player.constraints = [player.leftConstraint, player.middleConstraint, player.mrConstraint, player.rightConstraint ]

Passons en revue le code étape par étape. le didMoveToView (_ :) La méthode est appelée chaque fois que la scène est présentée par une vue. Après avoir appelé le didMoveToView (_ :) méthode de la super-classe, nous redimensionnons la scène à la même taille que la vue actuelle. Cela garantit que la scène remplit toujours la taille de l'écran de l'appareil actuel et est correctement mise à l'échelle.

Nous accédons au sprite player que nous avons ajouté dans l'éditeur de scène Xcode en le recherchant par le nom que nous lui avons donné précédemment. Nous attribuons ensuite cette valeur à la joueur propriété.

Après avoir calculé le centre de la scène et spécifié une différence constante de 70,0, nous créons les contraintes du sprite. En utilisant le positionX (_ :) méthode de classe du SKConstraint classe, nous créons les contraintes de gauche, du milieu et de droite pour le sprite du joueur. Cette méthode nécessite un SKRange exemple en tant que paramètre qui, dans notre cas, est une plage avec une valeur constante. Si vous souhaitez examiner les contraintes et les plages possibles dans SpriteKit, je vous recommande de consulter la SKConstraint et SKRange références de classe.

Nous désactivons les contraintes gauche et droite, car nous ne voulons pas que celles-ci agissent sur le nœud du joueur lorsque le jeu commence. Enfin, nous attribuons ces contraintes à la contraintes propriété du noeud du joueur. Cette propriété est définie dans le SKNode classe.

Construisez et exécutez votre jeu sur n’importe quel simulateur ou appareil physique. Vous devriez maintenant voir que votre scène est correctement mise à l’échelle avec la voiture centrée en bas..

Vous pouvez voir que la voiture est maintenant contrainte au centre horizontal de la scène et peut être contrainte aux voies gauche et droite une fois que nous avons ajouté du mouvement au jeu..

2. Actions

Les actions dans SpriteKit sont représentées par le puissant SKAction classe. Les actions nous permettent d’animer et de déplacer facilement des sprites dans une scène. Ils sont exécutés par des nœuds et sont évalués par les API SpriteKit. Ils fonctionnent parallèlement aux contraintes et aux simulations physiques..

En plus de spécifier le rôle d’une action, vous pouvez également programmer son fonctionnement en la configurant. Vous pouvez, par exemple, suspendre et reprendre des actions ou configurer le comportement d'accélération d'une action. Cela vous donne un plus grand degré de contrôle car vous pouvez facilement accélérer ou ralentir certaines actions pour produire des éléments de jeu intéressants..

De la même manière que les nœuds peuvent avoir des nœuds enfants, il existe trois types d'actions pouvant avoir des actions enfants:

  • séquence actions, qui exécutent un tableau d'actions les unes après les autres
  • groupe actions, qui exécutent un tableau d'actions en même temps
  • en répétant actions, qui répètent une action unique un nombre de fois ou indéfiniment

Vous pouvez créer des actions par programme ou dans l'éditeur de scène de Xcode, ce que nous avons utilisé dans le didacticiel précédent. Nous allons utiliser les deux techniques dans ce tutoriel.

Ouvrir MainScene.sks et cliquez sur l'icône à côté de la Animer bouton en bas à gauche de la scène pour faire apparaître le Action Editor View.

Ensuite, faites défiler dans le Bibliothèque d'objets de la droite et trouver le Action de déplacement article. Cliquez et faites glisser ceci dans la timeline du Action Editor View et placez-le sur le bord gauche comme indiqué ci-dessous:

Cela provoque l'exécution de l'action à 0:00, c'est-à-dire dès que la scène est présentée. Si l'action est placée ailleurs, l'action commence à s'exécuter après l'intervalle de temps indiqué en haut de la chronologie..

Passez votre souris sur l'action et cliquez sur la petite flèche en bas à gauche. Dans la fenêtre qui apparaît, cliquez sur le bouton infini bouton à gauche. Cela provoque l'action à répéter pour toujours.

L'action étant toujours sélectionnée, ouvrez le Inspecteur d'attributs à droite et changez le Décalage Y valeur à 100.

Les autres valeurs spécifient que la voiture démarre animera immédiatement (Heure de début) et chaque 1 seconde (Durée) se déplacera 0 points dans le X direction et 100 dans le direction (Décalage). le Fonction de synchronisation Cette propriété peut être utilisée pour démarrer et / ou arrêter progressivement une action. Dans ce cas, nous utilisons Linéaire, ce qui signifie que la voiture se déplace toujours à la même vitesse.

Enfin, pour tester l’action, cliquez sur le bouton Animer bouton en bas à gauche de l'éditeur de scène. La barre d'outils inférieure doit virer au bleu et la voiture devrait commencer à monter.

Avec l'action de déplacement mise en œuvre, il est temps de créer les actions horizontales par programme. Avant de le faire, nous devons ajouter un peu de logique afin que les boutons du jeu puissent contrôler la voiture..

Créez un nouveau fichier en choisissant le iOS> Source> Fichier Swift modèle et nommez-le LaneStateMachine.

Ajoutez le code suivant au nouveau fichier:

import GameplayKit classe LaneStateMachine: GKStateMachine  classe LaneState: GKState var playerNode: PlayerNode init (player: PlayerNode) playerNode = player classe LeftLane: LaneState annulation de la fonction isValidNextState (stateClass: AnyClass) -> Bool if. MiddleLane.self return true return false func didEnterWithPreviousState (previousState: GKState?) PlayerNode.moveInDirection (.Left, toLane: self) classe MiddleLane: LaneState override func isValidNextState (stateClass: AnyClass) -> si stateClass == LeftLane.self || stateClass == RightLane.self return true return false écrasement func didEnterWithPreviousState (previousState: GKState?) si previousState est LeftLane playerNode.moveInDirection (.Droit, toLane: self) sinon si previousState est LeftLane playerNode.moveInDirection (.Droit, toLane: self) sinon si previousState est RightLane playerNode.moveIndirection ( .Left, toLane: self) class RightLane: LaneState override func isValidNextState (stateClass: AnyClass) -> Bool si stateClass == MiddleLane.self return true return false override func didEnterWithPreviousState (previousState: GKState?) playerNode.moveInDirection (.Right, toLane: self)

Tout ce code utilise le nouveau framework GameplayKit pour créer une machine à états qui représente les trois voies et leurs mouvements dans le jeu. Si vous voulez mieux comprendre ce que fait ce code, consultez mon tutoriel sur GameplayKit.

Ensuite, ouvrez PlayerNode.swift et ajoutez les deux méthodes suivantes à la PlayerNode classe:

func disableAllConstraints () leftConstraint.enabled = false middleConstraint.enabled = false rightConstraint.enabled = false func moveInDirection (direction: ButtonDirection, toLane lane: LaneState) disableAllConstraints () laisse changerInX = (direction == .Left)? -70.0: 70.0 let rotation = (direction == .Left)? M_PI / 4: -M_PI / 4 let duration = 0.5 let moveAction = SKAction.moveByX (CGFloat (changeInX), y: 0.0, duration: duration) let rotationAction = SKAction.rotateByAngle (CGFloat (rotation), durée: durée / 2) rotationAction.timingMode = .EaseInEaseOut let rotationSequence = SKAction.sequence ([rotationAction, rotationAction.reversedAction ()]) let gestGroup = SKAction.group ([moveAction, rotationSequence]) let complétion = SKAction.runBlock () - Void dans lane case est LeftLane: self.leftConstraint.enabled = vrai cas est MiddleLane: self.middleConstraint.enabled = vrai cas est RightLane: self.rightConstraint.enabled = true par défaut: break let sequenceAction = SKAction.sequence ([moveGroup, achèvement]) runAction (sequenceAction)

le disableAllConstraints () méthode est une méthode pratique pour désactiver les contraintes du nœud du joueur.

Dans moveInDirection (_: toLane :), nous déterminons dans quelle direction la voiture doit se déplacer horizontalement, -70,0 en se déplaçant à gauche et +70,0 quand on bouge bien. Nous calculons ensuite l'angle correct (en radians) pour faire pivoter la voiture lors de son déplacement. Notez que les nombres positifs représentent une rotation dans le sens antihoraire.

Après avoir spécifié une durée constante, nous créons les actions de déplacement et de rotation à l'aide du moveByX (_: y: duration :) et rotateByAngle (_: duration :) méthodes de classe, respectivement. Nous créons une séquence de rotation pour faire revenir la voiture à son état antérieur au mouvement. le Action inversée () méthode crée automatiquement l'inverse d'une action pour vous.

Ensuite, nous créons une action de groupe de mouvements pour exécuter le déplacement horizontal et la rotation en même temps. Enfin, nous créons une action d'achèvement pour exécuter une fermeture lorsqu'elle est exécutée. Dans cette fermeture, nous découvrons la voie dans laquelle se trouve actuellement la voiture et activons la contrainte correcte pour cette voie..

Ouvrir ViewController.swift et ajouter une propriété, stateMachine, de type LaneStateMachine! au ViewController classe.

classe ViewController: UIViewController var stateMachine: LaneStateMachine!…

Remplacer les implémentations de viewDidLoad () et didPressButton (_ :) dans le ViewController classe avec les éléments suivants:

écrasez func viewDidLoad () super.viewDidLoad () let skView = SKView (frame: view.frame) let scene = MainScene (fileNamed: "MainScene")! skView.presentScene (scene) view.insertSubview (skView, atIndex: 0) let left = LeftLane (joueur: scene.player) let middle = Lane (joueur: scene.player) let right = RightLane (joueur: scene.player) stateMachine = LaneStateMachine (états: [gauche, milieu, droite]) stateMachine.enterState (MiddleLane) @IBAction func didPressButton (expéditeur: UIButton) émetteur de commutateur.tag case ButtonDirection.Left.rawValue: commutateur stateMachine.currentState case is RightLane : l'état stateMachine.enterState (MiddleLane) est MiddleLane: stateMachine.enterState (LeftLane) par défaut: break case ButtonDirection.Right.rawValue: commutateur stateMachine.currentState cas est LeftLane: stateMachine.enterState (MiddleLane): case MiddleLane: stateMachine.enterState (RightLane) default: break default: break

Dans viewDidLoad (), on insère le SKView objet à l'index 0 de sorte que les boutons de contrôle sont visibles et nous initialisons également la machine à états.

Dans didPressButton (_ :), nous trouvons le bouton sur lequel l'utilisateur a appuyé, en fonction des balises des boutons, et entrons dans la bonne voie depuis laquelle se trouve actuellement la voiture..

Construisez et lancez le jeu. Appuyez sur le bouton gauche ou droit en bas de l'écran pour faire bouger la voiture. Vous devriez voir la voiture tourner et vous déplacer dans la direction du bouton sur lequel vous avez appuyé..

Notez que les icônes des boutons peuvent ne pas correspondre, comme indiqué ci-dessous.

Pour résoudre ce problème, ouvrez le catalogue d’actifs (Image.xcassets) et pour chaque image (Flèche gauche et Flèche droite) ensemble Mode de rendu à Image originale.

Conclusion

Vous devriez maintenant pouvoir utiliser les contraintes et les actions de SpriteKit avec confiance. Comme vous pouvez le constater, ces fonctionnalités du framework facilitent l'ajout d'animations et de mouvements à un jeu SpriteKit..

Dans le prochain tutoriel de cette série, nous allons examiner les nœuds de caméra dans SpriteKit afin que notre voiture ne sorte pas toujours du haut de l'écran. Après cela, nous examinerons en profondeur le système de simulation physique de SpriteKit en mettant l’accent sur les corps physiques et la détection de collision..

Comme toujours, assurez-vous de laisser vos commentaires dans les commentaires ci-dessous.