SpriteKit,返回主菜单按钮
SpriteKit, Back to Main Menu Button
我在实现一个将您从 GameScene 转到主菜单的按钮时遇到了问题。
这是我的 GameScene 代码:
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()
}
当我暂停游戏时,我将 exitButton 添加到 menuPausaLayer。这是我用于此按钮的代码:
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)
}
但它没有用...有一种方法可以创建一个函数来在 SKScene 之外更改场景 class??提前致谢:)
更新:这里是我用于按钮的自定义 class:
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()
}
}
}
正如向 Apple documents 解释的那样,SKNode
也有一个名为 parent
的属性,因此 SKSpriteNode
继承自 SKNode
然后在您的 class button: SKSpriteNode
(即在你的代码中直接添加到场景中)你可以这样做:
if let parent = self.parent where parent is SKScene {
let pScene = parent as! SKScene
// do whatever you want with your scene
}
您真的不应该从 SKScene 访问 ViewController 相关操作,而这正是您想要做的。相反,您的情节提要中应该有 UI 相关操作。
但是,您可以从 SKScene 访问父视图控制器。
使用This example你可以得到视图控制器如下:
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
}
}
然后在你的游戏场景中你会使用
(view!.parentViewController as! GameViewController).dismiss(animated: true, completion: nil)
在一个节点中,您将使用:
(scene!.view!.parentViewController as! GameViewController).dismiss(animated: true, completion: nil)
或者您可以向视图控制器添加自定义函数来执行上述操作。
Swift 3代码在上面的评论里
同样,不推荐。您应该 UI 制作故事板并离开游戏场景来玩游戏。导航控制器是一种理想的方式。
使用下面的函数都可以正常使用!谢谢!
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)
}
我在实现一个将您从 GameScene 转到主菜单的按钮时遇到了问题。
这是我的 GameScene 代码:
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()
}
当我暂停游戏时,我将 exitButton 添加到 menuPausaLayer。这是我用于此按钮的代码:
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)
}
但它没有用...有一种方法可以创建一个函数来在 SKScene 之外更改场景 class??提前致谢:)
更新:这里是我用于按钮的自定义 class:
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()
}
}
}
正如向 Apple documents 解释的那样,SKNode
也有一个名为 parent
的属性,因此 SKSpriteNode
继承自 SKNode
然后在您的 class button: SKSpriteNode
(即在你的代码中直接添加到场景中)你可以这样做:
if let parent = self.parent where parent is SKScene {
let pScene = parent as! SKScene
// do whatever you want with your scene
}
您真的不应该从 SKScene 访问 ViewController 相关操作,而这正是您想要做的。相反,您的情节提要中应该有 UI 相关操作。
但是,您可以从 SKScene 访问父视图控制器。
使用This example你可以得到视图控制器如下:
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
}
}
然后在你的游戏场景中你会使用
(view!.parentViewController as! GameViewController).dismiss(animated: true, completion: nil)
在一个节点中,您将使用:
(scene!.view!.parentViewController as! GameViewController).dismiss(animated: true, completion: nil)
或者您可以向视图控制器添加自定义函数来执行上述操作。
Swift 3代码在上面的评论里
同样,不推荐。您应该 UI 制作故事板并离开游戏场景来玩游戏。导航控制器是一种理想的方式。
使用下面的函数都可以正常使用!谢谢!
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)
}