2

I am using SpriteKit and trying to make a simple game with a main menu. I have already made the game but I am having trouble creating the main menu.

Below is my code for the main menu and I want it to change to the gameScene and start my game.

import SpriteKit

class MenuScene: SKScene {

    var aButton = SKShapeNode(circleOfRadius: 50)

    override func didMove(to view: SKView) {
        aButton.fillColor = SKColor.red
        aButton.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
        self.addChild(aButton)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let scene = GameScene(fileNamed: "aButton")
        scene?.scaleMode = .aspectFill
        view!.presentScene(scene!, transition: SKTransition.doorsOpenVertical(withDuration: 1))
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Raggy
  • 47
  • 4
  • Possible duplicate of [Main Menu In Swift](http://stackoverflow.com/questions/41665676/main-menu-in-swift) – SumNeuron Jan 24 '17 at 08:20

2 Answers2

1

Try changing this line:

let scene = GameScene(fileNamed: "aButton")

To this:

let scene = GameScene(size: self.scene.size)

The first line transitions to a .SKS file named "aButton". I assume you're trying to transition once the button is touched.

To do this, first give the button a name:

aButton.name = "button"

Then transition if it's touched. Your entire touchesBegan method should look something like this:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    let location = touches.first?.locationInNode(self)
    let touchedNode = self.nodeAtPoint(location)

    if touchedNode.name == "button" {
        let newScene = GameScene(size: self.scene.size)
        newScene.scaleMode = .aspectFill
        view!.presentScene(newScene, transition: SKTransition.doorsOpenVertical(withDuration: 1))
    }
}
Nik
  • 1,664
  • 2
  • 14
  • 27
  • For some reason, I got an error with the touches.anyObject so I changed it to touches.first? then it worked for me. Thank you so much for your help!! – Raggy Nov 08 '16 at 05:19
  • I apologise if this is a stupid question: why does the `aButton` need a name? Or, in other words, why can't the check be: `if touchedNode == aButton { do stuff }` ? – Confused Nov 09 '16 at 14:09
  • @Confused It saves you from having to make the node global. If the node already needs to be global, it doesn't really matter, unless you want multiple nodes to have the same name because they have the same action – Nik Nov 09 '16 at 14:12
  • so, for simple games (by simple people, like me) just comparing a node to its reference is fine? – Confused Nov 09 '16 at 14:14
  • @Confused Yes, for the most part. If you have multiple nodes with the same action, you can give them all the same name, instead of doing multiple "or" checks in the if statement – Nik Nov 09 '16 at 14:17
  • Sorry, that's not what I'm asking. I'm trying to ascertain if it's possible to NOT use .name of an SKNode, and simply use the reference for comparisons. – Confused Nov 09 '16 at 14:32
  • @Confused Yes you can. As long as the node is global – Nik Nov 09 '16 at 14:39
  • Sorry, one more question: `let newScene = GameScene(size: self.scene.size)` this is getting the size of the `scene`... but where and how did `scene` become a reference that could be queried about its size? – Confused Nov 09 '16 at 14:45
  • Assuming `self` is an instance of itself, namely `GameScene`, how is it that `scene` is a reference to an `SKScene`? – Confused Nov 09 '16 at 14:50
  • @Confused Hmmm. I'm not sure. I'm sure someone who knows more about this than me has the answer to this. Maybe make a question... Sorry – Nik Nov 09 '16 at 14:52
  • I've partially resolved this, and found part of my problem, in Swift 3, this is all slightly different, and the `.scene` of `self` is an `optional`... but still confused ;) – Confused Nov 09 '16 at 14:56
0

I have posted a fairly thorough - yet basic - example for making a main menu is Swift3 for SKSpriteKit over here. In relation to your question, which attempts to do so programmatically rather than via the storyboard, I am also just copy-pasting the relevant part below:

Custom SKViews

Let's say, like this M.W.E., you want a menu, a difficulty, and a game scene.

Then you can make a series of custom SKViews to transition between.

enter image description here

GameViewController

This code loads the menuScene:

override func viewDidLoad() {
    super.viewDidLoad()

    let menuScene = MenuScene(size: view.bounds.size)

    let skView = view as! SKView
    skView.showsFPS = true
    skView.showsNodeCount = true
    skView.ignoresSiblingOrder = true
    menuScene.scaleMode = .resizeFill
    skView.presentScene(menuScene)

}

MenuScene

class MenuScene: SKScene {

    let playButton = SKLabelNode()


    override init(size: CGSize) {
        super.init(size: size)

        backgroundColor = SKColor.white

        playButton.fontColor = SKColor.black
        playButton.text = "play"

        playButton.position = CGPoint(x: size.width / 2, y: size.height / 2)

        addChild(playButton)

    }


    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let touchLocation = touch!.location(in: self)

        if playButton.contains(touchLocation) {

            let reveal = SKTransition.doorsOpenVertical(withDuration: 0.5)
            let difficultyScene = DifficultyScene(size: self.size)
            self.view?.presentScene(difficultyScene, transition: reveal)

        }

    }


}

DifficultyScene

class DifficultyScene: SKScene {

    let easyButton = SKLabelNode()
    let hardButton = SKLabelNode()
    let menuButton = SKLabelNode()


    override init(size: CGSize) {
        super.init(size: size)

        backgroundColor = SKColor.white

        easyButton.fontColor = SKColor.black
        easyButton.text = "easy"

        hardButton.fontColor = SKColor.black
        hardButton.text = "hard"

        menuButton.fontColor = SKColor.black
        menuButton.text = "menu"

        easyButton.position = CGPoint(x: size.width / 2, y: size.height / 2)
        hardButton.position = CGPoint(x: size.width / 2, y: size.height / 2 - easyButton.fontSize * 2)
        menuButton.position = CGPoint(x: size.width / 4 * 3, y: size.height / 4)

        addChild(easyButton)
        addChild(hardButton)
        addChild(menuButton)

    }


    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let touchLocation = touch!.location(in: self)

        if easyButton.contains(touchLocation) {
            let reveal = SKTransition.doorsOpenVertical(withDuration: 0.5)
            let gameScene = GameScene(size: self.size, difficulty: easyButton.text!)
            self.view?.presentScene(gameScene, transition: reveal)
        }

        if hardButton.contains(touchLocation) {
            let reveal = SKTransition.doorsOpenVertical(withDuration: 0.5)
            let gameScene = GameScene(size: self.size, difficulty: hardButton.text!)
            self.view?.presentScene(gameScene, transition: reveal)
        }

        if menuButton.contains(touchLocation){
            let reveal = SKTransition.doorsOpenVertical(withDuration: 0.5)
            let menuScene = MenuScene(size: self.size)
            self.view?.presentScene(menuScene, transition: reveal)
        }

    }


}

GameScene

add this to your GameScene:

init(size: CGSize, difficulty: String) {
        super.init(size: size)
        gameDifficulty = difficulty
    }

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
Community
  • 1
  • 1
SumNeuron
  • 4,850
  • 5
  • 39
  • 107