Matt Jahnes
Matt Jahnes

Reputation: 47

Changing Scenes In Spritekit, Detecting Touches on Buttons

I am attempting to change from a home scene to a game scene in Spritekit. When I run it in the simulator, there is no transition to the GameScene. I also added a print command to see if the touches on the play button were even being registered, and they were not. Here's the code. Thanks!

import SpriteKit

class HomeScene: SKScene {

    var playButton: SKSpriteNode?
    var gameScene: SKScene!

override func didMove(to view: SKView) {
    playButton = self.childNode(withName: "startButton") as? SKSpriteNode

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let pos = touch.location(in: self)
        let node = self.atPoint(pos)

        if node == playButton {
            let transition = SKTransition.fade(withDuration: 1)
            gameScene = SKScene(fileNamed: "GameScene")
            gameScene.scaleMode = .aspectFit
            self.view?.presentScene(gameScene, transition: transition)
            print("touch")
        }

    }
}

}

Upvotes: 0

Views: 1007

Answers (2)

Beny
Beny

Reputation: 138

I think you should use the node's name instead of the node itself for comparison in the touchesBegan... try something like this:

import SpriteKit

class HomeScene: SKScene {

    var playButton: SKSpriteNode?
    var gameScene: SKScene!

    override func didMove(to view: SKView) {
        playButton = self.childNode(withName: "startButton") as? SKSpriteNode

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let pos = touch.location(in: self)
            let node = self.atPoint(pos)

            if node.name == "startButton" {
                let transition = SKTransition.fade(withDuration: 1)
                gameScene = SKScene(fileNamed: "GameScene")
                gameScene.scaleMode = .aspectFit
                self.view?.presentScene(gameScene, transition: transition)
                print("touch")
            }

        }
    }
}

Hope it helps! :)

Upvotes: 0

nhiddink
nhiddink

Reputation: 235

The touches parameter inside of your touchesBegan(_: with:) method is of type Set<UITouch>, i.e. a set of touches. As stated in the Apple Documentation for Sets, a set is used when the order of the items in the collection are not a concern. Therefore, you cannot assume that the first item in touches is the first touch in the set. Knowing this, I recommend refactoring your code inside of HomeScene.swift to the following:

import SpriteKit

class HomeScene: SKScene {

    private var playButton: SKSpriteNode?

    override func sceneDidLoad() {
        self.playButton = self.childNode(withName: "//starButton") as? SKSpriteNode
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches {
            self.touchDown(atPoint: t.location(in: self))
        }
    }

    func touchDown(atPoint pos: CGPoint) {
        let nodes = self.nodes(at: pos)

        if let button = playButton {
            if nodes.contains(button) {
                let gameScene = SKScene(fileNamed: "GameScene")
                self.view?.presentScene(gameScene)
        }
    }
}

The touchDown(atPoint:) method does all the heavy lifting and touchesBegan(_: with:) is freed up to listen for touch events. Another thing to note when calling childNode(withName:):

  • Adding / before the name of the file starts searching for nodes beginning at the root of your file hierarchy.
  • Adding // before the name of the file starts searching for nodes beginning at the root of your file hierarchy, then recursively down the hierarchy.
  • Adding * before the name of the file acts as a character wildcard and allows you to search for file names that are wholly or partially unknown.

Upvotes: 1

Related Questions