{"id":31251,"date":"2017-07-08T03:01:06","date_gmt":"2017-07-07T17:01:06","guid":{"rendered":"http:\/\/www.rjmprogramming.com.au\/ITblog\/?p=31251"},"modified":"2018-07-10T09:56:37","modified_gmt":"2018-07-09T23:56:37","slug":"xcode-spritekit-game-collisions-tutorial","status":"publish","type":"post","link":"https:\/\/www.rjmprogramming.com.au\/ITblog\/xcode-spritekit-game-collisions-tutorial\/","title":{"rendered":"Xcode SpriteKit Game Collisions Tutorial"},"content":{"rendered":"<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode_collisions.jpg\"><img decoding=\"async\" style=\"border: 15px solid pink;\" alt=\"Xcode SpriteKit Game Collisions Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode_collisions.jpg\" title=\"Xcode SpriteKit Game Collisions Tutorial\"  style=\"float:left;\" \/><\/a><p class=\"wp-caption-text\">Xcode SpriteKit Game Collisions Tutorial<\/p><\/div>\n<p> The previous <a title='Xcode SpriteKit Game Primer Tutorial' href='#xskgpt'>Xcode SpriteKit Game Primer Tutorial<\/a> as shown below raved about the virtues of Xcode&#8217;s SpriteKit Game project&#8217;s cross-platform talents.  We leave you to read about that below, and move on, today, to a more realistic &#8220;Collision&#8221; view of a SpriteKit Game because, as most of us know, a lot of the video games and mobile games we are familiar with, work with the need to &#8220;do&#8221; the Physics regarding momentum and &#8220;Collisions&#8221;.<\/p>\n<p>Lots of SpriteKit Games have, you guessed it, Sprite objects, and it is explaining &#8220;Sprites&#8221; that we first need to talk about these Swift 3 (or you can use Objective-C if you like) coded projects that if left in a default working environment having &#8230;<\/p>\n<ul>\n<li>Scenes &#8230; with &#8230;<\/li>\n<li>Actions<\/li>\n<\/ul>\n<p> &#8230; can have their &#8220;Sprites&#8221; or other &#8220;visual elements&#8221; included via &#8230;<\/p>\n<ul>\n<li>Scene GameScene.sks Scene Builder visual method of scene building &#8230; and\/or &#8230;<\/li>\n<li>Scene GameScene.swift Swift 3 coding method to dynamically add and modify the &#8220;Sprites&#8221; and other &#8220;visual elements&#8221; along with the associated &#8220;Action&#8221; logics<\/li>\n<\/ul>\n<p>Looking at it as a programmer, would not recommend the limitations of just involving Scene GameScene.sks Scene Builder but it is there for you experts of methods similar to the good ol&#8217; IBOutlet linking days.  Below we mainly involve Scene GameScene.swift Swift 3 coding methods, but do, with our &#8220;obstacle&#8221;, link a Scene GameScene.sks Scene Builder &#8220;visual element&#8221; Sprite with the Scene GameScene.swift Swift 3 code.<\/p>\n<p>It seems to me we start life fascinated by collisions, with many early learning tools ready for baby&#8217;s gnawing away at a plaything in their mouth, one of life&#8217;s early &#8220;collision&#8221; places.  And think of all those bowls of food carefully pushed off high chairs &#8230; &#8220;Collisions 101&#8221;.<\/p>\n<p>Behind the scenes of you, the Xcode SpriteKit developer starting to &#8220;Animate&#8221; your &#8220;visual element&#8221; Sprites and others, will reach a point, in all likelihood, that to mimic real life when these &#8220;visual element&#8221; bodies meet the &#8220;Physics&#8221; of Xcode SpriteKit project code behind the scenes will be obeying the &#8220;law of momentum&#8221; which can be stated &#8230; thanks to <a target=_blank title='Momentum Conservation Principle - The Physics Classroom' href='http:\/\/www.physicsclassroom.com\/class\/momentum\/u4l2b.cfm'>Momentum Conservation Principle &#8211; The Physics Classroom<\/a> &#8230; <\/p>\n<blockquote cite='http:\/\/www.physicsclassroom.com\/class\/momentum\/u4l2b.cfm'><p>\nThe law of momentum conservation can be stated as follows. For a collision occurring between object 1 and object 2 in an isolated system, the total momentum of the two objects before the collision is equal to the total momentum of the two objects after the collision.\n<\/p><\/blockquote>\n<p>Believe me, though, you don&#8217;t need to know more than that, and that there is &#8220;Gravity&#8221; (or &#8220;ytivarg&#8221; for people reading this on your heads), to write SpriteKit Game code involving some &#8220;Physics&#8221; SpriteKit Project code functionality help.<\/li>\n<p>We have a long list of links that helped us work this tutorial below, but we want to turn your attention, first to a good read at <a target=_blank title='Collision detection: SKPhysicsContactDelegate' href='https:\/\/www.hackingwithswift.com\/read\/11\/5\/collision-detection-skphysicscontactdelegate'>Collision detection: SKPhysicsContactDelegate<\/a> as a precursor to our own experience of things <b>we need to do<\/b> to adapt a project that started out like <a title='Xcode SpriteKit Game Primer Tutorial' href='#xskgpt'>Xcode SpriteKit Game Primer Tutorial<\/a>&#8216;s SpriteKit project where we have one &#8220;obstruction&#8221; to a &#8220;rocket&#8221; Sprite, with its flare, that the user can zoom around the &#8220;obstacle&#8221; to clock up the elapsed (last) distance without colliding with the &#8220;obstruction&#8221;.<\/p>\n<ul>\n<li>Xcode Swift SpriteKit project GameScene.sks &#8230; <b>Show the Object Library at right &#8230; drop Colour Sprite into the Scene &#8230; Show the Attributes Inspector &#8230; gave it a name of &#8220;ourobstruction&#8221; &#8230;<\/b><\/li>\n<li>Found a good &#8220;rocket&#8221; image thanks to <a target=_blank title=\"rocket image help\" href='http:\/\/www.freeiconspng.com\/img\/40806'>Free Icons PNG<\/a> which <b>we modified for use via download to disk<\/b> and then via &#8230;<\/li>\n<li>Xcode <b>New -&gt; File -&gt; iOS -&gt; Resource -&gt; Asset Catalog -&gt; drag over various versions of rocket.png as above into the required slots<\/b><\/li>\n<li>GameScene.swift &#8230; class GameScene: SKScene<b>, SKPhysicsContactDelegate<\/b> {<br \/>\n     \/\/ rest of Swift code<br \/>\n}<\/li>\n<li>GameScene.swift &#8230;<br \/>\n<code><b><br \/>\n    fileprivate var label : SKLabelNode?<br \/>\n    fileprivate var spinnyNode : SKShapeNode?<br \/>\n    fileprivate var ylight : SKLightNode?<br \/>\n    fileprivate var ourcs : SKSpriteNode?<br \/>\n    fileprivate var ourobstacle : SKSpriteNode?<br \/>\n    fileprivate var ouran : SKAudioNode?<br \/>\n    public var anobstacle = SKSpriteNode()<br \/>\n<\/b><b><br \/>\n    \/\/init your categoryBitMask :<br \/>\n    public var carCategory:UInt32 = 0x1 << 0\n    public var slowCarCategory:UInt32 = 0x1 << 1\n<\/b><br \/>\n    class func newGameScene() -> GameScene {<br \/>\n        \/\/ Load 'GameScene.sks' as an SKScene.<br \/>\n        guard let scene = SKScene(fileNamed: \"GameScene\") as? GameScene else {<br \/>\n            print(\"Failed to load GameScene.sks\")<br \/>\n            abort()<br \/>\n        }<br \/>\n<b><\/b><br \/>\n        \/\/ Set the scale mode to scale to fit the window<br \/>\n        scene.scaleMode = .aspectFill<br \/>\n<b><\/b><br \/>\n        return scene<br \/>\n    }<br \/>\n<b><br \/>\n    func lightWithFinger(at pos: CGPoint){<br \/>\n        if let yourcs = self.ourcs?.copy() as! SKSpriteNode? {<br \/>\n            yourcs.position = pos<br \/>\n            yourcs.name = \"notspinny\"<br \/>\n            yourcs.physicsBody = SKPhysicsBody(rectangleOf:  CGSize(width: 1, height: 1))<br \/>\n            yourcs.physicsBody?.categoryBitMask = carCategory<br \/>\n            yourcs.physicsBody?.collisionBitMask = slowCarCategory<br \/>\n            yourcs.physicsBody?.contactTestBitMask = slowCarCategory<br \/>\n            yourcs.physicsBody?.isDynamic = false<br \/>\n            self.addChild(yourcs)<br \/>\n        }<br \/>\n        if let plight = self.ylight?.copy() as! SKLightNode? {<br \/>\n            plight.position = pos<br \/>\n            plight.lightColor = SKColor.orange<br \/>\n            plight.categoryBitMask = 0b0001<br \/>\n            plight.isEnabled = true<br \/>\n            self.addChild(plight)<br \/>\n        }<br \/>\n   }<\/b><br \/>\n<\/code>\n<\/li>\n<li>GameScene.swift &#8230;<br \/>\n<code><br \/>\n    func setUpScene() {<br \/>\n<b><\/b> <b><br \/>\n        \/\/ Get sprite node<br \/>\n        let pl = CGPoint(x: 0.0, y: 0.0)<br \/>\n        ourcs = SKSpriteNode(imageNamed: \"rocket.png\")<br \/>\n        ourcs?.name = \"notspinny\"<br \/>\n        ourcs?.position = pl<br \/>\n        ourcs?.physicsBody?.categoryBitMask = carCategory<br \/>\n        ourcs?.physicsBody?.collisionBitMask = slowCarCategory<br \/>\n        ourcs?.physicsBody?.contactTestBitMask = slowCarCategory<br \/>\n        ourcs?.physicsBody?.isDynamic = true<br \/>\n<\/b><b><br \/>\n        let negativeShader = SKShader(source: \"void main() { \" +<br \/>\n            \"    gl_FragColor = vec4(1.0 - SKDefaultShading().rgb, SKDefaultShading().a); \" +<br \/>\n            \"}\")<br \/>\n        self.ourcs?.shader = negativeShader<br \/>\n        self.ourcs?.anchorPoint = CGPoint(x: 0.5, y: 1.0)<br \/>\n<\/b><b><br \/>\n        \/\/ Get light node<br \/>\n        if let ylight = self.childNode(withName: \"light\") as? SKLightNode {<br \/>\n            ylight.position = pl \/\/self.convertPoint(toView: self.view)<br \/>\n            ylight.lightColor = SKColor.orange<br \/>\n            ylight.categoryBitMask = 0b0001<br \/>\n            ylight.isEnabled = true<br \/>\n        }<br \/>\n<\/b><br \/>\n     \/\/ more setUpScene code below<br \/>\n     }<br \/>\n<\/code>\n<\/li>\n<li>GameScene.swift &#8230;<br \/>\n<code><br \/>\n    #if os(watchOS)<br \/>\n    override func sceneDidLoad() {<br \/>\n        self.setUpScene()<b><br \/>\n        if let anobstacleNode = self.childNode(withName: \"ourobstacle\") as? SKSpriteNode {<br \/>\n            anobstacle = anobstacleNode<br \/>\n            if let atextureNode = self.childNode(withName: \"rocket\") as? SKTexture {<br \/>\n                let rocketAnimation = SKAction.animate(with: [atextureNode],<br \/>\n                                                       timePerFrame: 0.1)<br \/>\n                anobstacle.run(rocketAnimation)<br \/>\n            }<br \/>\n            anobstacle.physicsBody = SKPhysicsBody(rectangleOf:  CGSize(width: 10, height: 10))<br \/>\n            anobstacle.physicsBody?.categoryBitMask = slowCarCategory<br \/>\n            anobstacle.physicsBody?.collisionBitMask = carCategory<br \/>\n            anobstacle.physicsBody?.contactTestBitMask = carCategory<br \/>\n            anobstacle.name = \"obstacle\"<br \/>\n            anobstacle.physicsBody?.isDynamic = false<br \/>\n            self.addChild(anobstacle)<\/p>\n<p>        }<br \/>\n        physicsWorld.contactDelegate = self<\/b><br \/>\n    }<br \/>\n    #else<br \/>\n    override func didMove(to view: SKView) {<br \/>\n        self.setUpScene()<b><br \/>\n    if let anobstacleNode = self.childNode(withName: \"ourobstacle\") as? SKSpriteNode {<br \/>\n    anobstacle = anobstacleNode<br \/>\n    if let atextureNode = self.childNode(withName: \"rocket\") as? SKTexture {<br \/>\n    let rocketAnimation = SKAction.animate(with: [atextureNode],<br \/>\n    timePerFrame: 0.1)<br \/>\n    anobstacle.run(rocketAnimation)<br \/>\n    }<br \/>\n    anobstacle.physicsBody = SKPhysicsBody(rectangleOf:  CGSize(width: 10, height: 10))<br \/>\n    anobstacle.physicsBody?.categoryBitMask = slowCarCategory<br \/>\n    anobstacle.physicsBody?.collisionBitMask = carCategory<br \/>\n    anobstacle.physicsBody?.contactTestBitMask = carCategory<br \/>\n    anobstacle.name = \"obstacle\"<br \/>\n    anobstacle.physicsBody?.isDynamic = false<br \/>\n    self.addChild(anobstacle)<br \/>\n    }<br \/>\n        physicsWorld.contactDelegate = self<\/b><br \/>\n    }<br \/>\n    #endif<br \/>\n<\/code>\n<\/li>\n<p><code><b><br \/>\n    fileprivate var label : SKLabelNode?<br \/>\n    fileprivate var spinnyNode : SKShapeNode?<br \/>\n    fileprivate var ylight : SKLightNode?<br \/>\n    fileprivate var ourcs : SKSpriteNode?<br \/>\n    fileprivate var ourobstacle : SKSpriteNode?<br \/>\n    fileprivate var ouran : SKAudioNode?<br \/>\n    public var anobstacle = SKSpriteNode()<br \/>\n<\/b><b><br \/>\n    \/\/init your categoryBitMask :<br \/>\n    public var carCategory:UInt32 = 0x1 << 0\n    public var slowCarCategory:UInt32 = 0x1 << 1\n<\/b><b><br \/>\n    var totalDistance = CGFloat(0.0);<br \/>\n    var penUp = true;<br \/>\n    var lastX = CGFloat(0.0);<br \/>\n    var lastY = CGFloat(0.0);<br \/>\n<\/b><br \/>\n    class func newGameScene() -> GameScene {<br \/>\n        \/\/ Load 'GameScene.sks' as an SKScene.<br \/>\n        guard let scene = SKScene(fileNamed: \"GameScene\") as? GameScene else {<br \/>\n            print(\"Failed to load GameScene.sks\")<br \/>\n            abort()<br \/>\n        }<br \/>\n<b><\/b><br \/>\n        \/\/ Set the scale mode to scale to fit the window<br \/>\n        scene.scaleMode = .aspectFill<br \/>\n<b><\/b><br \/>\n        return scene<br \/>\n    }<br \/>\n<b><br \/>\n    func lightWithFinger(at pos: CGPoint){<br \/>\n        if let yourcs = self.ourcs?.copy() as! SKSpriteNode? {<br \/>\n            yourcs.position = pos<br \/>\n            yourcs.name = \"notspinny\"<br \/>\n            yourcs.physicsBody = SKPhysicsBody(rectangleOf:  CGSize(width: 1, height: 1))<br \/>\n            yourcs.physicsBody?.categoryBitMask = carCategory<br \/>\n            yourcs.physicsBody?.collisionBitMask = slowCarCategory<br \/>\n            yourcs.physicsBody?.contactTestBitMask = slowCarCategory<br \/>\n            yourcs.physicsBody?.isDynamic = false<br \/>\n            self.addChild(yourcs)<br \/>\n        }<br \/>\n        if let plight = self.ylight?.copy() as! SKLightNode? {<br \/>\n            plight.position = pos<br \/>\n            plight.lightColor = SKColor.orange<br \/>\n            plight.categoryBitMask = 0b0001<br \/>\n            plight.isEnabled = true<br \/>\n            self.addChild(plight)<br \/>\n        }<br \/>\n   }<\/b><br \/>\n<\/code>\n<\/li>\n<li>GameScene.swift &#8230; the Collision Detection function &#8230;<br \/>\n<code><b><br \/>\n    func didBegin(_ contact: SKPhysicsContact)<br \/>\n    {<br \/>\n        if contact.bodyA.node?.name == \"obstacle\" {<br \/>\n            totalDistance = pow(totalDistance,0.5)<br \/>\n            if totalDistance != CGFloat(0.0) {<br \/>\n            let userInfo = [\"message\": totalDistance];<br \/>\n            \/\/ Get label node from scene and store it for use later<br \/>\n            self.label = self.childNode(withName: \"\/\/helloLabel\") as? SKLabelNode<br \/>\n            if let label = self.label {<br \/>\n                 label.text = totalDistance.description<br \/>\n                 label.alpha = 1.0<br \/>\n                 label.run(SKAction.fadeIn(withDuration: 2.0))<br \/>\n            }<br \/>\n            }<br \/>\n            totalDistance = CGFloat(0.0)<br \/>\n        } else if contact.bodyB.node?.name == \"obstacle\" {<br \/>\n            totalDistance = pow(totalDistance,0.5)<br \/>\n            if totalDistance != CGFloat(0.0) {<br \/>\n           \/\/ Get label node from scene and store it for use later<br \/>\n            self.label = self.childNode(withName: \"\/\/helloLabel\") as? SKLabelNode<br \/>\n            if let label = self.label {<br \/>\n                label.text = totalDistance.description<br \/>\n                label.alpha = 1.0<br \/>\n                label.run(SKAction.fadeIn(withDuration: 2.0))<br \/>\n            }<br \/>\n        }<br \/>\n            totalDistance = CGFloat(0.0)<br \/>\n        } else if ((contact.bodyA.node?.position.x)! &lt; CGFloat(100.0) && (contact.bodyA.node?.position.y)! &lt; CGFloat(100.0) && (contact.bodyA.node?.position.x)! &gt; CGFloat(0.0) && (contact.bodyA.node?.position.y)! &gt; CGFloat(0.0)) {<br \/>\n            totalDistance = pow(totalDistance,0.5)<br \/>\n            if totalDistance != CGFloat(0.0) {<br \/>\n            \/\/ Get label node from scene and store it for use later<br \/>\n            self.label = self.childNode(withName: \"\/\/helloLabel\") as? SKLabelNode<br \/>\n            if let label = self.label {<br \/>\n                label.text = totalDistance.description<br \/>\n                label.alpha = 1.0<br \/>\n                label.run(SKAction.fadeIn(withDuration: 2.0))<br \/>\n            }<br \/>\n        }<br \/>\n            totalDistance = CGFloat(0.0)<br \/>\n        } else if (penUp) {<br \/>\n            lastX = (contact.bodyA.node?.position.x)!<br \/>\n            lastY = (contact.bodyA.node?.position.y)!<br \/>\n            penUp = false;<br \/>\n        } else {<br \/>\n            totalDistance += (((contact.bodyA.node?.position.x)! - lastX) * ((contact.bodyA.node?.position.x)! - lastX))<br \/>\n            totalDistance += (((contact.bodyA.node?.position.y)! - lastY) * ((contact.bodyA.node?.position.y)! - lastY))<br \/>\n            lastX = (contact.bodyA.node?.position.x)!<br \/>\n            lastY = (contact.bodyA.node?.position.y)!<br \/>\n            print(totalDistance)<br \/>\n        }<br \/>\n    }<\/b><br \/>\n<\/code>\n<\/li>\n<\/ul>\n<p>And you can see <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/GameScene.swift_GETME\" title=\"GameScene.swift\">GameScene.swift<\/a> Swift 3 code here.<\/p>\n<p>And of great help, thanks, were &#8230;<\/p>\n<ul>\n<li><a target=_blank href='http:\/\/www.techotopia.com\/index.php\/A_Swift_iOS_8_Sprite_Kit_Collision_Handling_Tutorial' title='An iOS 10 Sprite Kit Collision Handling Tutorial'>An iOS 10 Sprite Kit Collision Handling Tutorial<\/a><\/li>\n<li><a target=_blank href='https:\/\/stackoverflow.com\/questions\/34367268\/displaying-a-uialertcontroller-in-gamescene-spritekit-swift' title='ios - Displaying a UIAlertController in GameScene (SpriteKit\/Swift) - Stack Overflow'>ios &#8211; Displaying a UIAlertController in GameScene (SpriteKit\/Swift) &#8211; Stack Overflow<\/a><\/li>\n<li><a target=_blank href='https:\/\/www.hackingwithswift.com\/read\/11\/5\/collision-detection-skphysicscontactdelegate' title='Collision detection: SKPhysicsContactDelegate - a free Hacking with Swift tutorial'>Collision detection: SKPhysicsContactDelegate &#8211; a free Hacking with Swift tutorial<\/a><\/li>\n<li><a target=_blank href='https:\/\/stackoverflow.com\/questions\/44339599\/didbegin-contact-not-being-called-in-swift' title='collision detection - didBegin contact not being called in Swift - Stack Overflow'>collision detection &#8211; didBegin contact not being called in Swift &#8211; Stack Overflow<\/a><\/li>\n<li><a target=_blank href='https:\/\/stackoverflow.com\/questions\/32209725\/how-to-set-contactdelegate-for-physicsworld-in-spritekit' title='ios - How to set contactDelegate for physicsWorld in SpriteKit? - Stack Overflow'>ios &#8211; How to set contactDelegate for physicsWorld in SpriteKit? &#8211; Stack Overflow<\/a><\/li>\n<li><a target=_blank href='https:\/\/www.hackingwithswift.com\/example-code\/games\/how-to-add-physics-to-an-skspritenode' title='How to add physics to an SKSpriteNode - free Swift 3 example code'>How to add physics to an SKSpriteNode &#8211; free Swift 3 example code<\/a><\/li>\n<li><a target=_blank href='https:\/\/stackoverflow.com\/questions\/40824938\/collision-in-swift-3-sprite-kit-xcode-8' title='collision in swift 3 sprite kit Xcode 8 - Stack Overflow'>collision in swift 3 sprite kit Xcode 8 &#8211; Stack Overflow<\/a><\/li>\n<li><a target=_blank href='https:\/\/stackoverflow.com\/questions\/26438108\/ios-swift-didbegincontact-not-being-called' title='ios - Detecting collisions in sprite kit - Stack Overflow'>ios &#8211; Detecting collisions in sprite kit &#8211; Stack Overflow<\/a><\/li>\n<li><a target=_blank href='https:\/\/stackoverflow.com\/questions\/20572309\/detecting-collisions-in-sprite-kit' title='ios - Detecting collisions in sprite kit - Stack Overflow'>ios &#8211; Detecting collisions in sprite kit &#8211; Stack Overflow<\/a><\/li>\n<li><a target=_blank href='https:\/\/developer.apple.com\/documentation\/spritekit\/skaction' title='SKAction - SpriteKit | Apple Developer Documentation'>SKAction &#8211; SpriteKit | Apple Developer Documentation<\/a><\/li>\n<\/ul>\n<hr>\n<p id='xskgpt'>Previous relevant <a target=_blank title='Xcode SpriteKit Game Primer Tutorial' href='https:\/\/www.rjmprogramming.com.au\/ITblog\/xcode-spritekit-game-primer-tutorial\/'>Xcode SpriteKit Game Primer Tutorial<\/a> is shown below.<\/p>\n<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf\"><img decoding=\"async\" style=\"float:left; border: 15px solid pink;\" alt=\"Xcode SpriteKit Game Primer Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.jpg\" title=\"Xcode SpriteKit Game Primer Tutorial\"   \/><\/a><p class=\"wp-caption-text\">Xcode SpriteKit Game Primer Tutorial<\/p><\/div>\n<p>We&#8217;re always on the lookout for the word &#8220;cross&#8221; within I.T. circles (<font size=1>not because we have any anger management issues, but<\/font>), because it might mean some relief from &#8220;platform fatigue&#8221;.  By that, we mean that the number of different devices and platforms you write code for, and hope to achieve just the one codebase, makes you pay attention, especially when working in an IDE when the word &#8220;cross&#8221; is prominent.<\/p>\n<p>And so it was as we upgraded our MacBook Pro&#8217;s Xcode to version 8.3.1, and that set into play a revisit of this great IDE and a revisit of one of the great anticipatory parts of a good upgrade, the revisit to an IDE&#8217;s File -&gt; New Project functionality.  Xcode did not disappoint, offering templates for Apple platforms &#8230;<\/p>\n<ul>\n<li>iOS &#8230; Apple iPhones and iPads and iPods<\/li>\n<li>watchOS &#8230; Apple watch<\/li>\n<li>tvOS &#8230; Apple TV<\/li>\n<li>macOS &#8230; Apple Mac OS X &#8230; as with this MacBook Pro &#8230; and &#8230; da, da da da da da, da da da &#8230;<\/li>\n<li>Cross-platform &#8230; yay!!!! &#8230; feature today&#8217;s project of choice &#8230;<br \/>\n<code><br \/>\nCross-platform SpriteKit Game<br \/>\n<\/code>\n<\/li>\n<\/ul>\n<p>Now the test using &#8220;Cross-platform SpriteKit Game&#8221; would be, for us, is integrating with all those other (albeit, only, Apple) platforms be seamless and easy?  And turn away now in both a horizontal and vertical direction to avoid spoiler alert &#8230; you were warned &#8230; yes, as long as you have an Apple Developer Signup going if you might send your game to the Apple Store, otherwise you can do unit testing with device simulators.  And that is where, for us, those Apple white leads become so important for real device testing with the MacBook Pro&#8217;s USB ports (hang on to your older version MacBook Pros?!) interfacing hardwarewise with the Apple white leads and softwarewise with the MacBook Pro&#8217;s iTunes desktop application, first up, where any Syncing and\/or Ejecting of those real devices can take place, and be the springboard for Xcode projects to Product -&gt; Destination (or via some much more self-explanatory &#8220;top of screen&#8221; ways, now, with Xcode 8.3.1) to manage lots of device scenarios.  And you&#8217;ll want that using Xcode&#8217;s File -&gt; New Project -&gt; Cross-platform -&gt; Cross-platform SpriteKit Game work, because you&#8217;ll get a lot of work done fast.  By the way, we pick Objective-C as the language of project rather than the newer Swift for today.<\/p>\n<p>Which brings us to today&#8217;s &#8220;Cross-platform SpriteKit Game&#8221; work.  Yes, you guessed it &#8230; Hello World &#8230; but we do a few easy embellishments, which we&#8217;ll outline below, but we also say that you may get from our PDF <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf'>slideshow<\/a> presentation today &#8230;<\/p>\n<ul>\n<li>Open Xcode (IDE) desktop application (now 8.3.1 for us) on MacBook Pro<\/li>\n<li>File -&gt; New Project -&gt; Cross-platform -&gt; Cross-platform SpriteKit Game  &#8230; see <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=3'>slide 3<\/a> &#8230; etcetera etcetera etcetera<\/li>\n<li>ensure Project -&gt; General (tab) -&gt; Signing -&gt; Team involves a real option, if you intend to do more than unit testing and debugging in Simulators<\/li>\n<li>ensure Project -&gt; General (tab) -&gt; Deployment Info -&gt; Deployment Target involves a version low enough to cover the operating system of all your devices &#8230; we lowered it to 10.0 to cater for our iPad  &#8230; see <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=7'>slide 7<\/a><\/li>\n<li>we add some Emojis into the Share folder&#8217;s GameScene.sks &#8220;scene&#8221;&#8216;s &#8220;helloLabel&#8221;&#8216;s Attribute Inspector&#8217;s &#8220;Text&#8221; field via Edit -&gt; Emoji and Symbols submenu &#8230; see <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=6'>slide 6<\/a><\/li>\n<li>we change the Share folder&#8217;s GameScene.sks &#8220;scene&#8221;&#8216;s &#8220;helloLabel&#8221;&#8216;s Attribute Inspector&#8217;s we change &#8220;Rotation&#8221;, &#8220;Color&#8221;, &#8220;font&#8221; fields (which is pretty intuitive) for some variety &#8230; see <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=10'>slide 10<\/a><\/li>\n<li>we start to look at the Share folder&#8217;s Actions.sks &#8220;scene&#8221;&#8216;s &#8220;Pulse&#8221;&#8216;s Attribute Inspector&#8217;s &#8220;Fade In&#8221;, &#8220;Fade Out&#8221;, &#8220;Scale&#8221; actions &#8230; see <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=11'>slide 11<\/a> and <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=12'>slide 12<\/a> (to see its context in total time)<\/li>\n<li>we want to add code to introduce audio to application and start looking at GameScene.h and GameScene.m where code changes will take place &#8230; see <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=15'>slide 15<\/a> and <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=16'>slide 16<\/a> and <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=17'>slide 17<\/a> and <a target=_blank title='Click picture' href='http:\/\/www.rjmprogramming.com.au\/Mac\/Xcode\/spritexcode.pdf#page=18'>slide 18<\/a> &#8230; so, what we do for &#8230;\n<ol>\n<li>adding audio &#8220;notes of a piano&#8221; (that we had floating around) into the project&#8230; and, before we forget, thanks to <a target=_blank title='Useful link' href='http:\/\/stackoverflow.com\/questions\/11482999\/how-to-play-a-sound-with-avaudioplayer'>this very usefiul link<\/a> here &#8230;<br \/>\nunder iOS -&gt; Support Files (group) TwoFinger-&gt;Gesture New Group &#8230; call it &#8216;resource&#8217; &#8230;<br \/>\nagree to any Bundle Group relationships &#8230; that makes this Group permeate to all the different Target platform apps when building &#8230;<br \/>\ndrag those audio files to the &#8216;resource&#8217; Group &#8230;<br \/>\ncheck in Project -&gt; Build Phases -&gt; Copy Bundle Resources that those audio files happen that (anticipated) way &#8230; otherwise &#8230; Gooooooooogggggggggllllleee!\n<\/li>\n<li>low sound at a touch down or mouse down event &#8230;<br \/>\nGameScene.h <b>changes<\/b> as per &#8230;<br \/>\n<code><br \/>\n\/\/<br \/>\n\/\/  GameScene.h<br \/>\n\/\/  Cross Two<br \/>\n\/\/<br \/>\n\/\/  Created by pgAgent on 12\/4\/17.<br \/>\n\/\/  Copyright \u00a9 2017 RJM Programming. All rights reserved.<br \/>\n\/\/<br \/>\n<b><\/b><br \/>\n#import &lt;SpriteKit\/SpriteKit.h&gt;<br \/>\n<b>#import &lt;AVFoundation\/AVFoundation.h&gt;<\/b><br \/>\n<b><\/b><br \/>\n@interface GameScene : SKScene<br \/>\n+ (GameScene *)newGameScene;<br \/>\n@end<br \/>\n<\/code><br \/>\nGameScene.m <b>changes<\/b> up the top as per &#8230;<br \/>\n<code><br \/>\n\/\/<br \/>\n\/\/  GameScene.m<br \/>\n\/\/  Cross Two<br \/>\n\/\/<br \/>\n\/\/  Created by pgAgent on 12\/4\/17.<br \/>\n\/\/  Copyright \u00a9 2017 RJM Programming. All rights reserved.<br \/>\n\/\/<br \/>\n<b><\/b><br \/>\n#import \"GameScene.h\"<br \/>\n<b><\/b><br \/>\n@implementation GameScene {<br \/>\n    SKShapeNode *_spinnyNode;<br \/>\n    SKLabelNode *_label;<br \/>\n    <b>AVAudioPlayer *player;<\/b><br \/>\n}<br \/>\n\/\/ ... more code below<br \/>\n<\/code><br \/>\nGameScene.m <b>changes<\/b> up the top of (void)setUpScene as per us making that sound be the lowest A on your normal piano (ie. A0.mp3) &#8230;<br \/>\n<code><br \/>\n\/\/ ... more code above<br \/>\n- (void)setUpScene {<br \/>\n    <b>\/\/ Set up play sound<br \/>\n    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@\"%@\/A0.mp3\", [[NSBundle mainBundle] resourcePath]]];<br \/>\n    player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];<br \/>\n    player.numberOfLoops = 0;<\/b><br \/>\n<b><\/b><br \/>\n    \/\/ Get label node from scene and store it for use later<br \/>\n    _label = (SKLabelNode *)[self childNodeWithName:@\"\/\/helloLabel\"];<br \/>\n    _label.alpha = 0.0;<br \/>\n    [_label runAction:[SKAction fadeInWithDuration:2.0]];<br \/>\n\/\/ ... more code below<br \/>\n<\/code><br \/>\nGameScene.m <b>changes<\/b> bottom of (void)touchesBegan as per &#8230;<br \/>\n<code><br \/>\n\/\/ ... more code above<br \/>\n- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {<br \/>\n    [_label runAction:[SKAction actionNamed:@\"Pulse\"] withKey:@\"fadeInOut\"];<br \/>\n<b><\/b><br \/>\n    for (UITouch *t in touches) {<br \/>\n        [self makeSpinnyAtPoint:[t locationInNode:self] color:[SKColor greenColor]];<br \/>\n    }<br \/>\n    <b>[player play];<\/b><br \/>\n}<br \/>\n\/\/ ... more code below<br \/>\n<\/code><br \/>\nGameScene.m <b>changes<\/b> bottom of (void)mouseDown as per &#8230;<br \/>\n<code><br \/>\n\/\/ ... more code above<br \/>\n- (void)mouseDown:(NSEvent *)event {<br \/>\n    [_label runAction:[SKAction actionNamed:@\"Pulse\"] withKey:@\"fadeInOut\"];<br \/>\n<b><\/b><br \/>\n    <b>[player play];<\/b><br \/>\n    [self makeSpinnyAtPoint:[event locationInNode:self] color:[SKColor greenColor]];<br \/>\n}<br \/>\n\/\/ ... more code below<br \/>\n<\/code>\n<\/li>\n<li>some higher sound Actions.sks actions &#8230; which requires only GUI style work &#8230;<br \/>\nat the Share folder&#8217;s Actions.sks &#8220;scene&#8221;&#8216;s &#8220;Pulse&#8221;&#8216;s Attribute Inspector&#8217;s Object Library&#8217;s &#8220;PlaySoundFileNamed Action&#8221; drag into the desired timeslot and fill out &#8220;Start Time&#8221;, &#8220;Duration&#8221; and &#8220;Filename&#8221; (from a dropdown that should contain entries for each of those *.mp3 files you added into the project earlier) &#8230;<br \/>\nrepeat at different times for some &#8220;bird chirping&#8221; feeling randomosity, as required\n<\/li>\n<\/ol>\n<\/li>\n<li>to prepare the ground for the next run USB plug in any real device you want to test run, via USB port and Apple lead &#8230;<\/li>\n<li>to further prepare the ground for the next run, visit Product -&gt; Destination and pick appropriate Simulator or real device  &#8230;<\/li>\n<li>to test a device whether simulated or real Product -&gt; Run &#8230; and on a real device it will leave an installed version should it build correctly, and that you can revisit and run separate to being hooked up to the MacBook Pro, after you use the MacBook Pro&#8217;s iTunes device button Eject option, when you&#8217;ve finished testing, and want to unplug the real device <font size=1>&#8230; and &#8220;let it be mobile&#8221;, <strike>man<\/strike>person<strike>age<\/strike><\/font><\/li>\n<\/ul>\n<p>Get a few real devices and simulators going &#8230; and &#8230; <strike>&#8220;Weird Forest Sounds&#8221; (was the vision, but)<\/strike>&#8220;an instructional Xcode 8.3.1 Cross-platform SpriteKit Game project tutorial&#8221; YouTube video follows <strike>(above the MacBook Pro&#8217;s fan problems today &#8230; <font size=5>cut, cut!<\/font>)<\/strike>.<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/v5rEmWVIO6o\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d29566' onclick='var dv=document.getElementById(\"d29566\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/cross-platform\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d29566' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n<hr>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d31251' onclick='var dv=document.getElementById(\"31251\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/swift\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d31251' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The previous Xcode SpriteKit Game Primer Tutorial as shown below raved about the virtues of Xcode&#8217;s SpriteKit Game project&#8217;s cross-platform talents. We leave you to read about that below, and move on, today, to a more realistic &#8220;Collision&#8221; view of &hellip; <a href=\"https:\/\/www.rjmprogramming.com.au\/ITblog\/xcode-spritekit-game-collisions-tutorial\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,12,15,20,37,40],"tags":[84,2253,476,477,585,626,631,725,1974,940,997,2173,2174,1227,1319,1473],"class_list":["post-31251","post","type-post","status-publish","format-standard","hentry","category-animation","category-elearning","category-games","category-ios","category-tutorials","category-xcode","tag-animation-2","tag-collision","tag-game","tag-games-2","tag-ide","tag-ios","tag-iphone","tag-mac-os-x","tag-momentum","tag-physics","tag-programming","tag-sprite","tag-spritekit","tag-swift","tag-tutorial","tag-xcode"],"_links":{"self":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/31251"}],"collection":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/comments?post=31251"}],"version-history":[{"count":10,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/31251\/revisions"}],"predecessor-version":[{"id":39345,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/31251\/revisions\/39345"}],"wp:attachment":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/media?parent=31251"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/categories?post=31251"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/tags?post=31251"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}