Reputation: 23
I'm having trouble with implementing a button that will take you to the main menu from the GameScene.
This is my GameScene code:
let stoneLayer: SKNode = SKNode()
let cardLayer: SKNode = SKNode()
let menuPausaLayer: SKNode = SKNode()
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
backgroundColor = SKColor.blackColor()
addChild(stoneLayer)
addChild(cardLayer)
addChild(menuPausaLayer)
//Creazione posizioni carte
for i in 0...15 {
let cardLocation = SKSpriteNode(color: .orangeColor(), size: CGSize(width: cardWidth, height: cardHeight))
cardLocation.position = CGPointMake(cardLocPosition[i].x, cardLocPosition[i].y)
cardLocation.texture = SKTexture(imageNamed: "location")
cardLocation.zPosition = -90
addChild(cardLocation)
//grid[i] = 0
}
//Pulsanti
pauseButton.position = pauseButtonPosition
addChild(pauseButton)
loadDeck()
}
When I pause the Game, I add the exitButton to the menuPausaLayer. Here the code i use for this button:
let exitButton = button(buttonTexture: "pauseMenuButton",
buttonWidth: menuPausaBottonWidth,
buttonHeight: menuPausaBottonHeight,
action: {exit()}
})
func exit() {
print("Back to Main Menu")
let newScene = MainMenuScene(size: UIScreen.mainScreen().bounds.size)
newScene.scaleMode = .AspectFill
scene?.view?.presentScene(newScene)
}
But it did not works... There is a way to create a function to change scene outside of the SKScene class?? Thanks in advance :)
UPDATE: Here the custom class i use for the button:
class button: SKSpriteNode {
//NSCoder non supportato
required init(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
var buttonTexture: SKTexture
var buttonWidth: CGFloat
var buttonHeight: CGFloat
var action: () -> Void
init(buttonTexture: String, buttonWidth: CGFloat, buttonHeight: CGFloat, action: () -> Void) {
self.buttonTexture = SKTexture(imageNamed: buttonTexture)
self.buttonWidth = buttonWidth
self.buttonHeight = buttonWidth
self.action = action
super.init(texture: self.buttonTexture, color: .whiteColor(), size: CGSize(width: buttonWidth, height: buttonHeight))
userInteractionEnabled = true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for _ in touches {
let scale = SKAction.scaleTo(1.1, duration: 0.1)
runAction(scale)
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(scene!)
let touchedNode = nodeAtPoint(location)
let scale = SKAction.scaleTo(1.0, duration: 0.1)
runAction(scale)
if touchedNode.containsPoint(location) {
action()
}
}
}
Upvotes: 2
Views: 1073
Reputation: 35402
As explained to the Apple documents, SKNode
has also an attribute named parent
so SKSpriteNode
is inherited from SKNode
then in your class button: SKSpriteNode
(that in your code is directly added to the scene) you can do:
if let parent = self.parent where parent is SKScene {
let pScene = parent as! SKScene
// do whatever you want with your scene
}
Upvotes: 1
Reputation: 1129
You really should not be accessing ViewController related actions from an SKScene, which is what you want to do. Instead, you should have UI related actions in your storyboard.
However, you can get to the parent view controller from an SKScene.
Using This example you can get the view controller as follows:
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.nextResponder()
//swift 3: parentResponder = parentResponder!.next()
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
Then in your Game Scene you would use
(view!.parentViewController as! GameViewController).dismiss(animated: true, completion: nil)
In one node, you would use:
(scene!.view!.parentViewController as! GameViewController).dismiss(animated: true, completion: nil)
Or you could add a custom function to your view Controller to do the above.
Swift 3 code is in the comments above
Again, not recommended. You should storyboard your UI and leave the game scene to play the game. A navigation Controller is an ideal way to do that.
Upvotes: 0
Reputation: 23
Using the following function all works properly! Thanks!
func exit() {
print("Back to Main Menu")
if let parent = exitButton.parent where parent is SKScene {
let parentScene = parent as! SKScene
// do whatever you want with your scene
print ("YES")
let skView = parentScene.view! as SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.multipleTouchEnabled = false
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
let mainMenuScene = MainMenuScene(size: skView.bounds.size)
mainMenuScene.scaleMode = .ResizeFill //.AspectFill
skView.presentScene(mainMenuScene)
}
Upvotes: 0