Combiner la puissance de SpriteKit et de SceneKit

Ce que vous allez créer

introduction

SpriteKit et SceneKit sont des infrastructures iOS conçues pour permettre aux développeurs de créer facilement des éléments 2D et 3D dans des jeux occasionnels. Dans ce tutoriel, je vais vous montrer comment combiner le contenu créé dans les deux frameworks en une vue unique pour utiliser les API fournies par Apple..

Vous y parviendrez en ajoutant un simple bouton lecture / pause et des fonctionnalités de suivi du pointage à une scène 3D SceneKit grâce à l’utilisation d’une interface 2D SpriteKit..

Ce tutoriel nécessite au moins Xcode 6+ et une expérience préalable du contenu de base de SpriteKit et de SceneKit. Sinon, je vous recommande de lire d'abord certains de nos tutoriels Tuts + sur SpriteKit et SceneKit..

Il est également recommandé de disposer d'un périphérique iOS physique à utiliser pour les tests, ce qui nécessite un compte de développeur iOS actif et payant. Vous devrez également télécharger le projet de démarrage depuis GitHub..

1. Configuration du projet

Lorsque vous ouvrez le projet de démarrage, vous verrez que, en plus de la valeur par défaut AppDéléguer et ViewController classes, vous avez également deux autres classes, MainScene et OverlayScene.

le MainScene classe est une sous-classe de SCNScene et fournit le contenu 3D de votre application. De même, le OverlayScene classe est une sous-classe de SKScene et contient le contenu 2D SpriteKit dans votre application.

N'hésitez pas à regarder les implémentations de ces classes. Cela devrait vous sembler familier si vous avez une expérience de SpriteKit et de SceneKit. Dans ton ViewController la classe viewDidLoad méthode, vous trouverez également le code permettant de configurer une base SCNView exemple.

Générez et exécutez votre application sur le simulateur iOS ou sur votre périphérique physique. À ce stade, votre application contient un cube en rotation bleu..

Il est temps d'ajouter une scène SpriteKit au-dessus du contenu 3D. Ceci est fait en réglant la superpositionSKScene la propriété sur tout objet qui se conforme à la SCNSceneRenderer protocole, dans notre exemple, c'est la SCNView exemple. Dans ViewController.swift ajouter les lignes suivantes au viewDidLoad méthode:

override func viewDidLoad () … self.spriteScene = OverlayScene (taille: self.view.bounds.size) self.sceneView.overlaySKScene = self.spriteScene

Lorsque vous construisez et exécutez votre application à nouveau, vous constaterez que vous disposez maintenant d'un bouton de pause placé en bas à gauche et d'une étiquette de partition en bas au centre de la vue de votre application..

Vous vous demandez peut-être pourquoi il vaut mieux utiliser cette propriété plutôt que d’ajouter un SKView en tant que sous-vue du SCNView objet. Quand le superpositionSKScene propriété est utilisée, les composants 2D et 3D de votre application utilisent le même contexte OpenGL pour afficher le contenu à l'écran. Cela fonctionne nettement mieux que la création de deux vues distinctes, chacune ayant son propre contexte OpenGL et son propre pipeline de rendu. Même si la différence est négligeable pour cette configuration simple, les performances obtenues en scènes plus longues peuvent être inestimables..

2. Interaction SceneKit et SpriteKit

Il existe de nombreuses manières différentes de transférer des informations entre vos MainScene et OverlayScene les instances. Dans ce tutoriel, vous allez utiliser l'observation clé-valeur, KVO en abrégé..

Avant de mettre en œuvre la possibilité de suspendre l'animation du cube, vous devez d'abord ajouter cette fonctionnalité à la scène SpriteKit. Dans OverlayScene.swift, ajouter la méthode suivante à la OverlayScene classe:

override func touchesEnded (touches: Set, withEvent event: UIEvent) let touch = touches.first as? UITouch laisse location = touch? ?LocationInNode (self) si self.pauseNode.containsPoint (location!) If! Self.paused self.pauseNode.texture = SKTexture (imageNamed: "Bouton de lecture") else self.pauseNode. texture = SKTexture (imageNamed: "Bouton Pause") self.paused =! self.paused

le touchesEnded (_: withEvent :) Cette méthode est appelée lorsque l'utilisateur lève son doigt sur l'écran de l'appareil. Dans cette méthode, vous vérifiez si l'utilisateur a touché le bouton de pause et mettez la scène à jour en conséquence. Générez et exécutez à nouveau votre application pour vérifier que cette pièce du puzzle fonctionne correctement.

Nous devons maintenant arrêter la rotation du cube 3D lorsque l'utilisateur a appuyé sur le bouton de pause. Revenir à ViewController.swift et ajoutez la ligne suivante au viewDidLoad méthode:

remplacer func viewDidLoad () … self.spriteScene.addObserver (self.sceneView.scene !, forKeyPath: "en pause", options: .New, context: nil)

Enfin, ajoutez la méthode suivante à MainScene.swift pour activer l'observation des valeurs-clés:

override func observeValueForKeyPath (keyPath: String, objet ofObject: AnyObject, modification: [NSObject: AnyObject], contexte: UnsafeMutablePointer) si keyPath == "en pause" self.paused = change [NSKeyValueChangeNewKey] comme! Bool

Si vous générez et exécutez votre application à nouveau, le cube devrait cesser de tourner lorsque vous appuyez sur le bouton de pause.

Tout comme des informations peuvent être transférées d'une scène SpriteKit à une scène SceneKit, vous pouvez également envoyer des données d'instances SceneKit à des instances SpriteKit. Dans cette application simple, vous allez ajouter un point à la partition chaque fois que le cube est exploité par l'utilisateur. Dans ViewController.swift, ajoutez la méthode suivante:

override func touchesEnded (touches: Set, withEvent event: UIEvent) let touch = touches.first as? UITouch laisser location = touch? .LocationInView (self.sceneView) laisser hitResults = self.sceneView.hitTest (location !, options: nil) pour obtenir le résultat (hitResults as! [SCNHitTestResult]) si result.node == (self. sceneView.scene as! MainScene) .cubeNode self.spriteScene.score + = 1

Notez que nous avons utilisé le touchesEnded (_: withEvent :) méthode plutôt qu'un UITapGestureRecognizer, parce que UIGestureRecognizer les objets provoquent la touchesEnded (_: withEvent :) méthode à exécuter de manière très incohérente. Puisque vous utilisez cette méthode pour le bouton de pause, vous devez être sûr qu’elle sera appelée chaque fois que l’utilisateur tapera sur l’écran..

dans le touchesEnded (_: withEvent :) méthode, nous effectuons un test de localisation pour la position finale d'une touche dans votre sceneView. Si l'emplacement du toucher correspond à l'emplacement du cube, un point est ajouté au score de votre spriteScene. Le texte de la scène se mettra automatiquement à jour grâce à l'observateur de propriété du But propriété dans le OverlayScene classe.

Exécutez à nouveau votre application et appuyez sur le cube pour vérifier que l'étiquette de la partition est mise à jour chaque fois que le cube est exploité..

Le bouton de pause et l’étiquette de partition expliquent comment vous pouvez transférer des informations entre des scènes SpriteKit et SceneKit. Cependant, ces informations ne se limitent pas aux valeurs numériques et booléennes, elles peuvent correspondre au type de données que votre projet a besoin d’être..

3. Utilisation de scènes SpriteKit en tant que matériaux SceneKit

En plus de pouvoir superposer une scène SpriteKit sur une scène SceneKit, vous pouvez également utiliser un SKScene exemple en tant que matériau pour la géométrie SceneKit. Ceci est fait en assignant un SKScene objecter à la Contenu propriété d'un SCNMaterialProperty objet. Cela vous permet d'ajouter facilement un matériau animé sur n'importe quel objet 3D..

Regardons un exemple. Dans votre application, vous allez ajouter une simple animation de transition de couleur au cube au lieu du bleu statique actuel. dans le init méthode du MainScene classe, remplace le bloc de code suivant:

override init () super.init () let cube = SCNBox (largeur: 3, hauteur: 3, longueur: 3, chamferRadius: 0) let cubeMaterial = SCNMaterial () cubeMaterial.diffuse.contents = UIColor.blueColor () cube. materials = [cubeMaterial] self.cubeNode = SCNNode (géométrie: cube) self.cubeNode.runAction (SCNAction.repeatActionForever (SCNAction.rotateByX (0, y: 0.01, z: 0, durée: 1.0 / 60.0)))…

avec ce bloc de code:

override init () super.init () let cube = SCNBox (largeur: 3, hauteur: 3, longueur: 3, chanfreinRadius: 0) laisse materialScene = SKScene (taille: CGSize (largeur: 100, hauteur: 100)) let backgroundNode = SKSpriteNode (color: UIColor.blueColor (), size: materialScene.size) backgroundNode.position = CGPoint (x: materialScene.size.width / 2.0, y: materialScene.size.height / 2.0) materialScene.addChild (backgroundNode). let blueAction = SKAction.colorizeWithColor (UIColor.blueColor (), colorBlendFactor: 1, durée: 1) let redAction = SKAction.colorizeWithColor (UIColor.redColor (), colorBlendFactor: 1, durée: 1) let greenAction = SKActionColoré .greenColor (), colorBlendFactor: 1, durée: 1) backgroundNode.runAction (SKAction.repeatActionForever (SKAction.sequence ([blueAction, redAction, greenAction])))) laissez cubeMaterial = SCNMaterial () cubeMaterial.diffuse.contents =. materials = [cubeMaterial] self.cubeNode = SCNNode (geometry: cube) self.cubeNode.runAction (SCNAction.repeatAction Forever (SCNAction.rotateByX (0, y: 0.01, z: 0, durée: 1.0 / 60.0))))…

Cet extrait de code crée une simple SKScene instance avec un noeud de fond, qui est initialement bleu. Nous créons ensuite trois actions pour la transition du bleu au rouge et au vert. Nous exécutons les actions dans une séquence répétitive sur le nœud d'arrière-plan.

Bien que nous utilisions des couleurs de base dans notre exemple, tout ce qui peut être fait dans une scène SpriteKit peut être transformé en un matériau SceneKit..

Générez et exécutez votre application une dernière fois. Vous verrez que la couleur du cube passe du bleu au rouge et au vert.

Notez que la mise en pause de la scène SceneKit ne met pas la scène SpriteKit en pause. Pour mettre l'animation du matériau en pause, vous devez conserver une référence à la scène SpriteKit et la mettre en pause de manière explicite..

Conclusion

La combinaison du contenu de SpriteKit et de SceneKit peut être très bénéfique à bien des égards. Le fait de superposer une scène 2D au-dessus d’une scène 3D vous permet de créer une interface dynamique, ce qui se traduira par un gain de performances puisque les deux scènes utilisent le même contexte OpenGL et le même pipeline de rendu. Vous avez également appris à utiliser SpriteKit pour créer des matériaux animés pour des objets 3D. Si vous avez des commentaires ou des questions, laissez-les dans les commentaires ci-dessous.