Swift 3:通过覆盖SKView在SpriteKit中创建一个暂停菜单?

时间:2017-01-25 07:01:36

标签: ios swift sprite-kit skview

上下文

虽然有些游戏选择放弃暂停菜单 - 假设因为游戏时间较短,例如Don't Grind - 我个人认为暂停游戏是一项关键功能,并希望了解如何实施它在Swift 3中为SpriteKit。

我已经看到尝试使用UIAlertController来做到这一点,但是我 - 或许是错误的 - 相信更好的替代方案是在当前{{1}上覆盖SKView }}。

我看过Apple的DemoBots,看看我是否能弄清楚他们是如何暂停比赛的。但是,在我的设备上下载并运行它后,它会导致错误,所以我不想跟风。但是,如果有人能够彻底解释过多的文件,例如" LevelScene + Pause"," SceneManager"," SceneOperation"等等以及它们如何协同工作,也会很酷。

问题

如何在SKView上叠加SKView来制作暂停菜单?

最低工作范例

M.W.E., StackOverflow SpriteKit with Menu,是一个准系统"游戏"将答案语境化。请回答有关M.W.E的问题。

更新

以下是M.W.E的修改版本。该文件" GameScene"。 它考虑为要暂停的元素添加主节点,为暂停菜单添加另一个节点。

暂停菜单工作时,即使GameScene,背景仍然有效。 (尝试点击最左边的蓝色精灵)。

//

gameNode.isPaused = true

1 个答案:

答案 0 :(得分:2)

我在游戏场景中暂停游戏的问题已经挣扎了一段时间。

正如其他几个人在评论中所建议的那样,建立一个“暂停场景”,以便在游戏暂停时转换为一个有效的解决方案。这种方法可以避免在游戏暂停时或游戏停止时定时器在游戏场景中触发时可能遇到的问题。

为了实现暂停场景,我使用UIViewController的自定义子类来处理场景转换。

在我的CustomViewController

var sceneForGame: MyGameScene? //scene to handle gameplay
var paused: PauseScene? //scene to appear when paused

...

// presentPauseScene() and unpauseGame() handle the transition from game to pause and back

  func presentPauseScene() {
    //transition the outgoing scene
    let transitionFadeLength = 0.30
    let transitionFadeColor = UIColor.white
    let pauseTransition = SKTransition.fade(with: transitionFadeColor, duration: transitionFadeLength)
    pauseTransition.pausesOutgoingScene = true

    let currentSKView = view as! SKView
    currentSKView.presentScene(paused!, transition: pauseTransition)
  }

  func unpauseGame() {
    let transitionFadeLength = 0.30
    let transitionFadeColor = UIColor.white
    let unpauseTransition = SKTransition.fade(with: transitionFadeColor, duration: transitionFadeLength)
    unpauseTransition.pausesIncomingScene = false

    let currentSKView = view as! SKView
    currentSKView.presentScene(sceneForGame!, transition: unpauseTransition)
  }

MyGameScene类(SKScene的子类)中:

var parentViewController: CustomViewController?  // ref to the managing view controller 

...

   // invoke this func when you want to pause
  func setScenePause() {
    parentViewController?.presentPauseScene()
    self.isPaused = true
  }

...

// you may need a snippet like this in your game scene's didMove(toView: ) to wake up when you come back to the game
    else if self.isPaused {
      self.isPaused = false
    }

这是我的PauseScene实施。当用户点击暂停场景中的任何位置时,此版本将取消暂停,但endGameButton除外,该终止当前游戏:

struct PauseNames {
  static let endGameButton = "ENDGAME"
  static let pausedButton = "PAUSE"
}

class PauseScene: SKScene {

  var center : CGPoint?
  var pauseButton: SKSpriteNode?
  var endGameButton: SKSpriteNode?
  var parentViewController: CustomViewController?

  override func didMove(to view: SKView) {
    setUpScene()
  }

  func setUpScene() {
    self.backgroundColor = SKColor.white
    self.center = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
    self.isUserInteractionEnabled = false

    setUpSceneNodes()
    showPauseEndButtons()

  } // end setup scene

  func setUpSceneNodes() {
    let buttonScale: CGFloat = 0.5
    let smallButtonScale: CGFloat = 0.25

    let pauseOffset = //some CGPoint
    let endGameOffset = //some CGPoint
    pauseButton = SKSpriteNode(imageNamed: PauseNames.pausedButton)
    pauseButton?.name = PauseNames.pausedButton
    pauseButton?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    pauseButton?.position = self.center! + pauseOffset
    pauseButton?.alpha = 0
    pauseButton?.setScale(buttonScale)

    endGameButton = SKSpriteNode(imageNamed: PauseNames.endGameButton)
    endGameButton?.name = PauseNames.pausedButton
    endGameButton?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    endGameButton?.position = self.center! + endGameOffset
    endGameButton?.alpha = 0
    endGameButton?.setScale(smallButtonScale)
  }

  func showPauseEndButtons() {
    let buttonFadeInTime = 0.25
    let pauseDelay = 1.0

    self.addChild(pauseButton!)
    self.addChild(endGameButton!)

    pauseButton?.run(SKAction.fadeIn(withDuration: buttonFadeInTime))
    endGameButton?.run(SKAction.fadeIn(withDuration: buttonFadeInTime))
    self.run(SKAction.sequence([
      SKAction.wait(forDuration: pauseDelay),
      SKAction.run{ self.isUserInteractionEnabled = true }]))
  }

  func endGamePressed() {
    // add confrim logic
    parentViewController?.endGame()
  }

  func unpausePress() {
    parentViewController?.unpauseGame()
  }

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

      if endGameButton!.contains(touchLocation) {
        endGamePressed()
        return
      }
      else {
        unpausePress()
      }

    } // end for each touch
  } // end touchesBegan

  override func update(_ currentTime: TimeInterval) {
    /* Called before each frame is rendered */
  }

} //end class PauseScene

pauseButton实际上更像是一个横幅,用于通知用户此版本中的暂停状态)