Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. iOS SDK
Code

Créer un jeu de Blackjack dans Swift 3 et SpriteKit

by
Difficulty:IntermediateLength:LongLanguages:

French (Français) translation by New Lune (you can also view the original English article)

Final product image
What You'll Be Creating

Dans ce tutoriel, vous allez créer un jeu de blackjack dans SpriteKit à l'aide de Swift 3. Vous apprendrez à implémenter le toucher, à créer des animations visuelles et à beaucoup d'autres concepts qui seront utiles lors de la construction d'un jeu SpriteKit.

1. Création du projet et importation de ressources

Ouvrez Xcode et choisissez Create a new Xcode project ou choisissez New > Project... dans le menu File. Assurez-vous que iOS est sélectionné et choisissez le modèle Game.

new_project

Ensuite, choisissez ce que vous souhaitez pour le nom du produit, le nom de l'organisation et l'identificateur d'organisation. Assurez-vous que Language est défini sur Swift, Game Technology est défini sur SpriteKit, et Devices est configuré sur iPad.

project_options

Spécifiez un emplacement pour enregistrer les fichiers du projet et cliquez sur Create.

Importation des cours d'aide

Téléchargez le compte GitHub pour ce projet. A l'intérieur, vous verrez un dossier de classes. Ouvrez ce dossier et faites glisser tous les fichiers sur le dossier qui a le nom de ce que vous avez appelé votre projet, par exemple, le blackjack. Assurez-vous que Copy items if needed est vérifié ainsi que la cible principale dans la liste des cibles.

File options with Copy items if needed box checked

Importation des images

Aussi dans le tutoriel GitHub repo est un dossier nommé tutorial images. Dans le navigateur du projet, ouvrez Assets.xcassets et faites glisser toutes les images dans la barre latérale. Xcode créera automatiquement des atlas de texture à partir de ces images.

Tutorial images folder in GitHub

2. Mise en place du projet

Dans le navigateur du projet, il existe deux fichiers que vous pouvez supprimer (Gamescene.sks et Actions.sks). Supprimez ces deux fichiers et sélectionnez Move To Trash. Ces fichiers sont utilisés par l'éditeur de scène intégré de Xcode, qui peut être utilisé pour présenter vos projets de manière visuelle. Nous allons créer tout à travers le code, cependant, de sorte que ces fichiers ne sont pas nécessaires.

Ouvrez GameViewController.swift, supprimez son contenu et remplacez-le par ce qui suit.

La classe GameViewController hérite de UIViewController et aura une vue SKView. À l'intérieur de la méthode viewDidLoad, nous réduisons la propriété view pour une instance SKView, en utilisant le as! opérateur de type et configurons la vue.

Si vous deviez exécuter ce projet lorsque vous l'avez créé, vous pouvez remarquer le texte en bas à droite de l'écran. C'est ce que les propriétés de ShowFPS et de ShowNodeCount apparaissent, montrant les images par seconde sur lesquelles le jeu se déroule et le nombre de SKNodes visible dans la scène. Nous n'avons pas besoin de cette information, alors nous les définissons comme false.

La propriété ignoreSiblingOrder est utilisée pour déterminer l'ordre de dessin des SKNodes dans le jeu. Nous avons mis cela false ici parce que nous avons besoin de notre SKNodes pour dessiner dans l'ordre où ils sont ajoutés à la scène.

Enfin, nous définissons le mode d'échelle à .aspectFill, ce qui entraînera l'échelle du contenu de la scène pour remplir l'écran entier. Nous invoquons ensuite la méthode presenteScene(_ :) sur le skView qui présente ou "montre" la scène.

Ensuite, supprimez tout dans GameScene.swift et remplacez-le par ce qui suit.

Vous pouvez maintenant tester le projet et vous devriez présenter un écran noir vierge. Dans l'étape suivante, nous allons commencer à ajouter du contenu à notre scène.

3. Variables et Constantes

Entrez le code suivant au début de la classe GameScene juste en dessous où GameScene hérite de SKScene.

Nous créons ici un certain nombre de SKSpriteNodes. SKSpriteNodes sont utilisés pour créer un noeud coloré, ou plus communément à partir d'un SKTexture, qui est le plus souvent une image. Nous utilisons l'initialisation de la commodité init(color:size:) pour créer un nœud coloré clair MoneyContainer. Le MoneyContainer sera utilisé pour tenir l'argent que le joueur parie, et à la fin de chaque tour, nous allons animer ce mouvement vers celui qui a gagné le jeu. Placer tout l'argent dans ce seul nœud facilite l'animation de tout l'argent en même temps.

Ensuite, nous créons les constantes dealBtn, hitBtn et standBtn. Comme les noms le suggèrent, ceux-ci seront utilisés dans le jeu pour traiter, frapper et se tenir respectivement. Nous utilisons l'initialisation de la commodité init(imageNamed:), qui prend comme paramètre le nom de l'image sans extension.

Nous créons alors les trois constantes de money10, de money25 et de money50, qui sont du type MoneyMoney est une classe personnalisée qui étend SKSpriteNode et selon le type de moneyValue passé en tant que paramètre crée l'un des trois types de money différents. Le paramètre moneyValue est de type MoneyValue, qui est un enum. Jetez un oeil à la classe Money dans le projet GitHub repo pour voir comment tout cela fonctionne.

Enfin, nous créons un SKLabelNode à l'aide de l'initialisation du commutateur init(text:) qui prend comme paramètre le texte à afficher dans l'étiquette.

4. Mise en place de setupTable

Ajoutez ce qui suit sous la fonction didMove(to:).

Ici, nous initialisons une table constante et l'ajoutons à la scène en utilisant addChild(_:) qui prend comme paramètre le nœud à ajouter à la scène. Nous définissons la position de la table dans la scène et posons sa zPosition à -1. La propriété zPosition contrôle l'ordre dans lequel les nœuds sont dessinés. Le nombre le plus bas est tiré en premier, avec des nombres plus élevés tirés en ordre. Parce que nous avons besoin du table ci-dessous tout le reste, nous définissons sa zPosition en -1. Cela garantit qu'il est dessiné avant tout autre noeud.

Nous ajoutons également moneyContainer et instructionText à la scène. Nous configurons fontColor de instructionText en noir (la valeur par défaut est blanche).

Mettez à jour didMove(to:) à la suivante.

La méthode didMove(to:) est appelée immédiatement après la présentation de la scène par la vue. Généralement, c'est là que vous allez faire l'installation de votre scène et créer vos atouts. Si vous testez maintenant, vous devriez voir cette table et instructionText a été ajouté à la scène. Le moneyContainer est là aussi, mais vous ne pouvez pas le voir parce que nous l'avons créé avec une couleur claire.

5. Mise en œuvre de setupMoney

Ajoutez ce qui suit sous la méthode setupTable.

Ici, nous ajoutons simplement les instances de money et fixons leur position. Appelez cette méthode dans didMove(to:).

6. Mise en œuvre de setupButtons

Ajoutez ce qui suit sous la méthode setupMoney que vous avez créée dans l'étape ci-dessus.

Comme nous l'avons fait avec les fonds de l'étape précédente, nous ajoutons les boutons et définissons leurs positions. Ici, nous utilisons le name propriété afin que nous puissions identifier chaque bouton par code. Nous avons également défini le hitBtn et le standBtn pour être cachés, ou invisibles, en définissant la propriété isHidden sur true.

Maintenant, invoquez cette méthode dans didMove(to:).

Si vous exécutez l'application maintenant, vous devriez voir les instances de l'argent et les boutons ont été ajoutés à la scène.

7. Mettre en œuvre les touchesBegan

Nous devons implémenter la méthode touchesBegan(_:with:) afin de savoir quand les objets de la scène ont été touchés. Cette méthode est appelée lorsqu'un ou plusieurs doigts ont été touchés sur l'écran. Ajoutez ce qui suit dans les touchesBegan.

La propriété multiTouchEnabled de la vue de la scène est définie false par défaut, ce qui signifie que la vue ne reçoit que la première touche d'une séquence multitouch. Avec cette propriété désactivée, vous pouvez récupérer le contact à l'aide de first propriété calculée du jeu de touches car il n'y a qu'un seul objet dans l'ensemble.

Nous pouvons obtenir touchLocation dans la scène par la propriété de location du contact. Nous pouvons alors déterminer quel nœud a été touché en invoquant atPoint (_:) et en passant dans touchLocation.

Nous vérifions si la propriété de nom de touchedNode est égale à "money", et si nous savons qu'ils ont abordé l'une des trois instances d'argent. Nous initialisons une constante money en réduisant le touchedNode to Money, puis nous appelons la méthode de bet appelant la méthode getValue() sur la constante de money.

8. Mise en œuvre de bet

Entrez ce qui suit sous la fonction setupButtons que vous avez créée dans l'étape ci-dessus.

Nous nous assurons tout d'abord que le joueur n'essaie pas d'obtenir plus d'argent que ce qu'ils ont, et si c'est le cas, nous revenons simplement de la fonction. Sinon, nous ajoutons le rapport betAmount au pot, créez un tempMoney constant, définissez votre anchorPoint sur (0,0) et ajoutez-le à moneyContainer. Nous avons ensuite défini sa position et caché le dealBtn en définissant sa propriété isHidden sur false.

SKSpriteNodes possède une propriété anchorPoint par défaut (0,5,0,5). Le système de coordonnées place (0,0) en bas à gauche et (1,1) en haut à droite. Vous modifiez cette propriété de sa valeur par défaut si vous étiez en rotation le SKSpriteNode et que vous souhaitez qu'il tourne autour d'un point différent. Par exemple, si vous avez changé la propriété anchorPoint en (0,0), le SKSpriteNode tournerait de son coin inférieur gauche. Vous modifiez souvent cette propriété pour vous aider à vous positionner, comme nous l'avons fait ici.

Nous devons créer une instance des classes Pot et Player pour que ce code fonctionne. Ajoutez les éléments suivants avec les autres constantes et variables.

Si vous testez maintenant, vous pouvez appuyer sur l'un des fonds et l'ajouter à moneyContainer.

9. Mise en œuvre de deal

Ajoutez ce qui suit avec le reste de vos constantes et vos variables.

Le tableau allCards sera utilisé pour contenir toutes les cartes dans le jeu. Cela facilitera le passage à travers eux et les supprimer de la scène en une seule fois. Les constantes dealerCardsY et playerCardsY sont les positions des cartes sur l'axe y. Cela nous aidera à placer de nouvelles cartes. Le currentPlayerType est utilisé pour indiquer à qui s'adresser le prochain. Ce sera soit égal à celui du dealer ou du player1.

Inside didMove(to:), ajoutez ce qui suit.

Dans le code précédent, nous avons initialisé currentPlayerType dans une instance sans nom de la classe Player. Nous l'avons mis ici sur player1.

Nous devons créer un nouveau jeu de cartes avant de mettre en œuvre la méthode de l'opération. Entrez ce qui suit dans setupTable.

Maintenant, nous pouvons mettre en œuvre la fonction de transaction. Ajoutez ce qui suit sous la méthode de bet.

Cette méthode est assez grande, mais nécessaire pour implémenter la logique de transaction. Passons par étape. Nous initialisons une constante tempCard dans une instance de Card, définissons sa position et ajoutons-le à la scène. Nous avons besoin de cette carte dessinée dans une zPosition supérieure à 0, car la première carte du concessionnaire doit être à 0. Nous l'établissons à un nombre arbitraire—100 fera. Nous créons également une constante de newCard en invoquant la méthode getTopCard() du deck.

Ensuite, nous initialisons deux variables, whichPosition et whichHand, puis nous avons parcouru une logique pour déterminer leurs valeurs finales. Nous ajoutons ensuite newCard à la main appropriée (soit celle du joueur ou du revendeur). La constante xPos détermine la position x finale de la carte une fois qu'elle est finie d'animer.

La classe SKAction possède un certain nombre de méthodes de classe que vous pouvez appeler pour modifier les propriétés d'un noeud comme la position, l'échelle et la rotation. Nous appelons ici la méthode move(to:duration:), qui déplacera le nœud d'une position à l'autre. Cependant, pour exécuter le SKAction, vous devez invoquez la méthode run(_ :) d'un nœud et passez SKAction comme paramètre. Ici, cependant, nous invoquons la méthode run(_: completion:), ce qui entraînera l'exécution du code dans la fermeture d'achèvement une fois l'action terminée.

Une fois l'action terminée, nous permettons au joueur de parier en appelant setCanBet(canBet:) sur l'instance player1. Nous vérifions ensuite si currentPlayerType est une instance de Dealer et vérifiez que le dealer n'a qu'une seule carte en invoquant hand.getLength(). Si tel est le cas, nous définissons la première carte du dealer, dont nous aurons besoin à la fin du jeu.

Parce que la première carte du dealer est toujours face cachée jusqu'à la fin du jeu, nous avons besoin d'une référence à la première carte afin que nous puissions la montrer plus tard. Nous ajoutons cette carte au tableau allCards afin que nous puissions le supprimer plus tard, puis définir sa propriété zPosition à 0 car nous avons besoin de cette carte ci-dessous toutes les autres cartes. (Rappelez-vous que les autres cartes ont la position z 100.)

Si currentPlayerType n'est pas une instance de Dealer et que la longueur de la main n'est pas égale à 1, nous supprimez la tempCard et mettons newCard dans la même position, en vous assurant de régler sa zPosition sur 100.

Selon les règles du blackjack, le concessionnaire et le joueur obtiennent deux cartes pour démarrer le jeu. Ici, nous vérifions ce qu'est le currentPlayerType et le modifions au contraire. Parce que le concessionnaire a moins de deux cartes, nous reprenons la fonction de deal. Sinon, nous vérifions si le dealer et le player1 ont deux cartes et, si tel est le cas, nous vérifions si les cartes ont une valeur totale de 21—une main gagnante. Si l'un d'eux a 21, le jeu est fini parce que l'un d'eux a obtenu un blackjack. Si aucun d'entre eux n'a 21, donc nous montrons le standBtn et hitBtn et le jeu se poursuit.

Les règles du blackjack stipulent que le dealer doit être supérieur ou égal à 17. Les prochaines lignes de code vérifient si la valeur de main du dealer est inférieure à 17 et si elle invoque la méthode de deal. Si c'est 17 ou plus, le jeu est terminé. Enfin, si la valeur de main de player1 est supérieure à 21, le jeu est terminé car ils ont été bloqués.

Ce fut beaucoup de logique à traverser! Si quelque chose n'est pas clair, lisez-le à nouveau et prenez votre temps pour le comprendre.

Ensuite, nous devons mettre en œuvre la méthode du gameover.

Nous devons pouvoir savoir quand l'utilisateur a appuyé sur le bouton de transaction. Ajoutez le code suivant à la méthode touchesBegan(_:with:).

10. Implémentation de DoGameOver

Ensuite, entrez ce qui suit sous la méthode de deal que vous avez créée dans l'étape ci-dessus.

Nous obtenons la position x et y de la première carte dans le tableau allCards, qui est la première carte du concessionnaire. Ensuite, nous créons une tempCard constante en invoquant GetFirstCard sur le concessionnaire. Rappelez-vous que nous avons défini cet Card plus tôt dans la méthode du contrat? Ici, nous l'ajoutons à la scène, définissons sa position à l'aide des constantes tempCardX et tempCardY, et définissons sa zPosition sur 0, donc c'est sous les autres cartes.

Nous devons savoir qui a gagné le jeu, alors nous initialisons un winner variable en le rendant égal à player1, même si cela peut changer en fonction de si le dealer a effectivement gagné le jeu.

Nous avons ensuite parcouru une logique pour déterminer qui a gagné le jeu. Si le paramètre hasBlackjack est vrai, alors nous découvrons qui a gagné et revenir de la fonction. Sinon, nous poursuivons la logique pour savoir qui a gagné le jeu. Je ne vais pas aller pas à pas à travers cette logique, comme cela devrait être clair à comprendre. Peu importe qui a gagné, nous invoquons moveMoneyContainer(position:), qui prend comme paramètre le poste pour déplacer le conteneur d'argent. Ce sera la position y de la carte du dealer ou du player1.

11. Mise en œuvre de moveMoneyContainer

Entrez le code suivant sous la méthode doGameOver.

La méthode moveMoneyContainer(position:) déplace le moneyContainer pour quiconque a gagné le jeu, soit le joueur, soit le revendeur. Lorsque le SKAction est terminé, nous appelons resetMoneyContainer.

12. Implémentation de resetMoneyContainer

La méthode resetMoneyContainer supprime tous les fonds en invoquant la méthode removeAllChildren(), réinitialise le moneyContainer dans sa position d'origine et invoque newGame.

13. Mise en place de newGame

Ajoutez ce qui suit sous la méthode resetMoneyContainer que vous avez implémentée dans l'étape ci-dessus.

Ici, nous réinitialisons toutes les variables nécessaires et supprimez toutes les cartes de la scène en bouclant le tableau allCards et en appelant removeFromParent() sur chaque élément.

14. Mettre en œuvre le hitBtn et le standBtn

Tout ce qui reste pour compléter notre jeu est de mettre en œuvre les touches du hitBtn et du standBtn. Entrez ce qui suit dans la méthode touchBegan(_:with:).

Et maintenant, nous mettrons en œuvre les méthodes appelées dans le gestionnaire d'événements. Entrez les deux méthodes suivantes ci-dessous la méthode newGame.

Dans la méthode de hit, nous nous assurons que ce joueur peut parier, et si c'est le cas, nous avons mis le currentPlayerType sur player1, puis invoquez la méthode de deal et arrêtez le joueur de parier davantage.

Dans la méthode stand, nous invoquons setLielding sur player1, en passant par true. Nous vérifions ensuite si la valeur de main du dealer est inférieure à 17, et si c'est le cas, nous appelons une transaction, et si la main du dealer a 17 ou plus, cela signifie que le jeu est terminé.

Vous pouvez maintenant tester le jeu terminé.

Conclusion

Il s'agissait d'un long tutoriel avec une bonne logique cachée dans la méthode de transaction. Nous n'avons pas mis en œuvre l'utilisation du Pot et l'addition et la soustraction de l'argent de la banque du joueur. Pourquoi n'essayez-vous pas de faire cela comme un exercice pour terminer l'application?

Vous avez maintenant un jeu de blackjack pour être fier. Merci de votre lecture, et j'espère que vous avez trouvé ce tutoriel utile. Pendant que vous êtes ici, consultez certains de nos autres cours et tutoriels sur la programmation d'applications avec Swift et SpriteKit!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.