
Bonjour à tous! En prévision du lancement du cours
«Développeur iOS. Cours de base », nous avons organisé une autre
leçon ouverte . Ce webinaire est conçu pour les personnes qui ont de l'expérience dans le développement dans toutes les langues et plates-formes, mais qui souhaitent apprendre le langage Swift et maîtriser le développement pour iOS. Dans la leçon, nous avons examiné en détail la
syntaxe et les constructions clés du langage Swift , familiarisé avec les principaux outils de développement.
Les participants au webinaire ont appris:
- quelle est la langue Swift, quelles sont ses caractéristiques;
- Comment l'environnement de développement Xcode vous aide à démarrer
- comment créer un jeu simple pour iOS.
Le webinaire a été dirigé par
Alexei Sobolevsky , développeur iOS chez Yandex.
Faites-le vous-même Snake
Pour le travail, nous avons utilisé l'
environnement de développement intégré
Xcode . Il s'agit d'un environnement pratique, gratuit et fonctionnel créé par Apple.
Au tout début, nous avons créé un nouveau projet et sélectionné l'ensemble de base des fichiers «Game»:

Sans plus tarder, ils ont appelé le projet «Snake». Tous les paramètres ont été laissés par défaut, garantissant que SpriteKit était dans la ligne Game Technology.
Détails de la création du projet.Après avoir effectué les actions ci-dessus, une liste de fichiers créés automatiquement pour notre projet sera affichée dans la partie gauche de la fenêtre. L'un des fichiers les plus importants est
AppDelegate.swift , qui aide le système à communiquer avec notre code lorsque surviennent des événements importants pour l'application (lancement, push, clic sur le lien, etc.). Code de ce fichier:
Les fichiers tout aussi importants sont
GameScene.swift et
GameViewController.swift . La classe GameScene crée la scène et le GameViewController est responsable d'un écran de l'application que nous voyons (un écran - un GameViewController). Bien sûr, cette règle n'est pas toujours prise en charge, mais en général elle fonctionne. Puisque notre application est assez simple, nous n'aurons qu'un seul GameViewController. Commençons par lui.
Écrire un GameViewController
Nous supprimerons le code par défaut. Le contrôleur de vue dispose de plusieurs méthodes qui fonctionnent en fonction de l'état de l'écran. Par exemple,
viewDidLoad()
déclenché lorsque tous les éléments d'écran ont déjà été chargés et que l'écran est sur le point d'apparaître sur le smartphone. Puisque nous avons un jeu, nous devons placer la scène du jeu dans notre contrôleur de vue (c'est là que le serpent se déroulera et que tous les autres événements du jeu se produiront).
Créez une scène:
let scene = GameScene(size: view.bounds.size)
let est une constante et un mot-clé. Swift utilise également le mot clé var, qui est requis pour définir une variable. En utilisant
var , nous pouvons changer la valeur des variables plusieurs fois pendant l'exécution du programme. En utilisant let, nous ne pouvons pas changer la valeur des variables après l'initialisation.
Maintenant, nous devons nous assurer que la vue dans laquelle nous allons placer la scène créée correspond au type souhaité. Pour ce faire, utilisez la construction
guard - c'est la même chose que
if
, seulement dans l'autre sens (sinon):
guard let skView = view as? SKView else { return }
Après nous être assurés que l'élément screen correspond au type souhaité, nous y ajoutons notre scène:
skView.presentScene(scene)
Vous devez également afficher le nombre d'images par seconde (FPS):
skView.showsFPS = true
Affichez ensuite le nombre d'éléments de tous types sur la scène:
skView.showsNodeCount = true
Et faisons apparaître les éléments à l'écran quel que soit leur ordre dans la hiérarchie des éléments:
skView.ignoresSiblingOrder = true
Et n'oubliez pas que notre scène doit être étirée sur toute la largeur de l'écran:
scene.scaleMode = .resizeFill
Voici le code final du fichier
GameViewController.swift :
import UIKit import SpriteKit import GameplayKit class GameViewController: UIViewController { override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() setup() } private func setup() { guard let skView = view as? SKView else { return } let scene = GameScene(size: view.bounds.size) skView.showsFPS = true skView.showsNodeCount = true skView.ignoresSiblingOrder = true scene.scaleMode = .resizeFill skView.presentScene(scene) } }
Détails de la création du fichier GameViewController.swift.Donc, nous avons créé la scène, mais elle est vide, donc si nous exécutons l'émulateur maintenant, nous ne verrons qu'un écran noir.
Écrire une GameScene
Comme la dernière fois, nous supprimons la plupart du code, puis
effectuons les réglages nécessaires pour la scène . Il a également ses propres méthodes. Par exemple, depuis que nous avons ajouté notre scène au ViewController, nous avons besoin de la méthode
didMove()
:
override func didMove(to view: SKView) { setup(in: view) }
De plus, lorsque le jeu démarre, la méthode
Update()
est appelée pour chaque image:
override func update(_ currentTime: TimeInterval) { snake?.move() }
Et nous avons également besoin de quelques gestionnaires pour toucher l'écran:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return }
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return }
Comme vous le savez, Swift est célèbre pour la présence de
sucre syntaxique . Sucre syntaxique - ce sont des aspects techniques qui simplifient la vie du développeur, accélèrent l'écriture du code. Tout cela aide beaucoup à mettre en place la scène, ce que nous allons faire maintenant. Tout d'abord, définissez la couleur:
backgroundColor = SKColor.white
Étant donné que le serpent fonctionne dans un avion, nous n'avons pas besoin de physique, et vous pouvez le désactiver pour que le serpent ne tombe pas à cause de la gravité. De plus, nous n'avons pas besoin que le jeu tourne, etc.:
physicsWorld.gravity = .zero physicsWorld.contactDelegate = self physicsBody = SKPhysicsBody(edgeLoopFrom: frame) physicsBody?.allowsRotation = false physicsBody?.categoryBitMask = CollisionCategories.edgeBody physicsBody?.collisionBitMask = CollisionCategories.snake | CollisionCategories.snakeHead view.showsPhysics = true
Créez maintenant les boutons:
let counterClockwiseButton = ControlsFactory.makeButton(at: CGPoint(x: scene.frame.minX + 30, y: scene.frame.minY + 50), name: .counterClockwiseButtonName) addChild(counterClockwiseButton) let clockwiseButton = ControlsFactory.makeButton(at: CGPoint(x: scene.frame.maxX - 90, y: scene.frame.minY + 50), name: .clockwiseButtonName) addChild(clockwiseButton)
Lorsque vous avez écrit un morceau de code, vous devez vous demander si le code peut être amélioré ou refactorisé afin qu'il puisse être
réutilisé à l'avenir. Regardez, nous avons essentiellement deux boutons à l'écran, pour la création desquels le même code est utilisé. Ainsi, ce code peut être retiré dans une fonction distincte. Pour ce faire,
créez une nouvelle classe et, en conséquence, le fichier
ControlsFactory.swift avec le code suivant:
import SpriteKit final class ControlsFactory { static func makeButton(at position: CGPoint, name: String) -> SKShapeNode { let button = SKShapeNode() button.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 45, height: 45)).cgPath button.position = position button.fillColor = .gray button.strokeColor = UIColor.lightGray.withAlphaComponent(0.7) button.lineWidth = 10 button.name = name return button } }
Pour dessiner une pomme au hasard que notre serpent «mangera»,
créez la classe Apple et le fichier
Apple.swift :
import SpriteKit final class Apple: SKShapeNode { let diameter: CGFloat = 10 convenience init(at point: CGPoint) { self.init() path = UIBezierPath(ovalIn: CGRect(x: -diameter/2, y: -diameter/2, width: diameter, height: diameter)).cgPath fillColor = .red strokeColor = UIColor.red.withAlphaComponent(0.7) lineWidth = 5 position = point physicsBody = SKPhysicsBody(circleOfRadius: diameter / 2, center: .zero) physicsBody?.categoryBitMask = CollisionCategories.apple } }
Et nous décrivons notre pomme avec la fonction
createApple()
dans
GameScene.swift :
private func createApple() { let padding: UInt32 = 15 let randX = CGFloat(arc4random_uniform(UInt32(gameFrameRect.maxX) - padding) + padding) let randY = CGFloat(arc4random_uniform(UInt32(gameFrameRect.maxY) - padding) + padding) let apple = Apple(at: CGPoint(x: randX, y: randY).relative(to: gameFrameRect)) gameFrameView.addChild(apple) }
Eh bien, le tour est venu pour le serpent. Il sera composé de deux parties: le corps (
SnakeBodyPart.swift ) et la tête (
SnakeHead.swift ).
Code
SnakeBodyPart.swift :
import SpriteKit class SnakeBodyPart: SKShapeNode { init(at point: CGPoint, diameter: CGFloat = 10.0) { super.init() path = UIBezierPath(ovalIn: CGRect(x: -diameter/2, y: -diameter/2, width: diameter, height: diameter)).cgPath fillColor = .green strokeColor = UIColor.green.withAlphaComponent(0.7) lineWidth = 5 position = point physicsBody = SKPhysicsBody(circleOfRadius: diameter - 4, center: .zero) physicsBody?.isDynamic = true physicsBody?.categoryBitMask = CollisionCategories.snake physicsBody?.contactTestBitMask = CollisionCategories.edgeBody | CollisionCategories.apple } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Code
SnakeHead.swift :
import SpriteKit final class SnakeHead: SnakeBodyPart { init(at point: CGPoint) { super.init(at: point, diameter: 20) physicsBody?.categoryBitMask = CollisionCategories.snakeHead physicsBody?.contactTestBitMask = CollisionCategories.edgeBody | CollisionCategories.apple } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Cependant, nous ne vous
ennuierons pas avec une description de chaque ligne,
car les détails de la création du fichier GameScene.swift et des autres classes sont bien affichés dans la vidéo. Nous vous proposons uniquement de voir le code final de
GameScene.swift :
import SpriteKit import GameplayKit class GameScene: SKScene { var gameFrameRect: CGRect = .zero var gameFrameView: SKShapeNode! var startButton: SKLabelNode! var stopButton: SKLabelNode! var snake: Snake? override func didMove(to view: SKView) { setup(in: view) } override func update(_ currentTime: TimeInterval) { snake?.move() } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return } if let shapeNode = touchedNode as? SKShapeNode, touchedNode.name == .counterClockwiseButtonName || touchedNode.name == .clockwiseButtonName { shapeNode.fillColor = .green if touchedNode.name == .counterClockwiseButtonName { snake?.moveCounterClockwise() } else if touchedNode.name == .clockwiseButtonName { snake?.moveClockwise() } } else if touchedNode.name == .startButtonName { start() } else if touchedNode.name == .stopButtonName { stop() } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return } if let shapeNode = touchedNode as? SKShapeNode, touchedNode.name == .counterClockwiseButtonName || touchedNode.name == .clockwiseButtonName { shapeNode.fillColor = .gray } } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touchedNode = findTouchedNode(with: touches) else { return } if let shapeNode = touchedNode as? SKShapeNode, touchedNode.name == .counterClockwiseButtonName || touchedNode.name == .clockwiseButtonName { shapeNode.fillColor = .gray } }
Le résultat fut le jeu Snake le plus simple:

Il nous a fallu environ une heure et demie pour écrire le jeu. Si vous souhaitez acquérir des compétences en programmation dans Swift, répétez toutes les étapes vous-même. Au fait,
ici, vous aurez un accès complet à tous les fichiers de code qui ont été utilisés dans ce projet.