Ios Swift 3:通过叠加SKView在SpriteKit中创建暂停菜单? 上下文
虽然有一些游戏选择放弃暂停菜单,这可能是因为游戏持续时间较短,例如,我个人认为暂停游戏是一项关键功能,我想学习如何在Swift 3 for SpriteKit中实现它 我见过使用Ios Swift 3:通过叠加SKView在SpriteKit中创建暂停菜单? 上下文,ios,swift,sprite-kit,skview,Ios,Swift,Sprite Kit,Skview,虽然有一些游戏选择放弃暂停菜单,这可能是因为游戏持续时间较短,例如,我个人认为暂停游戏是一项关键功能,我想学习如何在Swift 3 for SpriteKit中实现它 我见过使用UIAlertController来实现这一点的尝试,这是可行的,但我——也许是错误的——认为更好的选择是将SKView覆盖在当前SKView之上 我看过苹果的,看看是否能弄明白他们是如何暂停游戏的。然而,在我的设备上下载并运行这个程序之后,它导致了一个错误,所以我不想这样做。然而,如果有人能彻底解释过多的文件,如“Le
UIAlertController
来实现这一点的尝试,这是可行的,但我——也许是错误的——认为更好的选择是将SKView
覆盖在当前SKView
之上
我看过苹果的,看看是否能弄明白他们是如何暂停游戏的。然而,在我的设备上下载并运行这个程序之后,它导致了一个错误,所以我不想这样做。然而,如果有人能彻底解释过多的文件,如“LevelScene+Pause”、“SceneManager”、“SceneOperation”等,以及它们是如何协同工作的,那也会很酷
问题:
如何将SKView
覆盖在游戏场景
上以创建暂停菜单
最低工作示例
M.W.E。,
,是一个将答案语境化的赤裸裸的“游戏”。请回答有关M.W.E.的问题
更新
下面是从M.W.E.文件“游戏场景”中修改的版本。
它考虑为要暂停的元素添加一个主节点和为暂停菜单添加另一个节点
暂停菜单工作时,即使gameNode.isPaused=true
,背景仍然工作。(试着点击最左边的蓝色精灵)
//
//GameScene.swift
//堆栈溢出
//
//萨姆纳于2017年1月17日创作。
//版权所有©2017萨姆纳。版权所有。
//
进口SpriteKit
导入游戏工具包
类游戏场景:SKScene{
var cam:SKCameraNode!
变量sprite=SKSpriteNode(图像名为:“sprite”)
变量sprite2=SKSpriteNode(图像名为:“sprite2”)
让pauseLabel=SKLabelNode(文本:“暂停!”)
/*
*
*开始:新代码
*
*/
让gameNode=SKNode()
var pauseMenuSprite:SKShapeNode!
让pauseMenuTitleLabel=SKLabelNode(文本:“暂停菜单”)
让pauseMenuContinueLabel=SKLabelNode(文本:“继续游戏?”)
让pauseMenuToMainMenuLabel=SKLabelNode(文本:“主菜单?”)
/*
*
*完:新代码
*
*/
var timeStart:Date!
init(大小:CGSize,难度:String){
super.init(大小:size)
游戏难度=难度
timeStart=Date()
/*
*
*开始:新代码
*
*/
pauseMenuSprite=SKShapeNode(rectOf:size)
/*
*
*完:新代码
*
*/
}
必需的初始化?(编码器aDecoder:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
覆盖func didMove(到视图:SKView){
backgroundColor=SKColor.white
打印(“以\(游戏难度)难度开始的游戏”)
//鳞片精灵
雪碧.设置刻度(0.3)
sprite2.设置刻度(0.3)
sprite.position=CGPoint(x:size.width/4,y:size.height/2)
sprite2.position=CGPoint(x:size.width/4*3,y:size.height/2)
/*
*
*开始:新代码
*
*/
gameNode.addChild(精灵)
gameNode.addChild(sprite2)
addChild(游戏节点)
/*
*
*完:新代码
*
*/
如果游戏难度=“难”{
设sprite3=SKSpriteNode(图像名为:“sprite”)
sprite3.设置刻度(0.3)
sprite3.position=CGPoint(x:size.width/4*2,y:size.height/2)
addChild(sprite3)
}
pauseLabel.fontColor=SKColor.black
pauseLabel.position=CGPoint(x:size.width/4*2,y:size.height/4)
addChild(pauseLabel)
}
func着陆(在点位置:CGPoint){
}
func touchMoved(拓扑点位置:CGPoint){
}
func接地(atPoint位置:CGPoint){
}
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
对于t in触地{self.tound(在点:t.location(in:self))}
}
覆盖功能触摸移动(touchs:Set,带有事件:UIEvent?){
对于触摸中的t{self.touchMoved(toPoint:t.location(in:self))}
}
覆盖函数touchesend(touchs:Set,带有事件:UIEvent?){
让我们先接触
让touchLocation=touch!.location(in:self)
让pausedTouchLocation=touch?位置(in:pausedemusprite)
如果sprite.contains(触摸位置){
打印(“你点击了蓝色精灵”)
/*
let alert=UIAlertController(标题:“警报”,消息:“消息”,首选样式:UIAlertControllerStyle.alert)
让action=UIAlertAction(标题:“Ok”,样式:。默认值){action in
//单击按钮时的句柄
let REVEL=SKTRANSION.doorsOpenVertical(持续时间:0.5)
让menuScene=menuScene(大小:self.size)
self.view?.presentScene(画面切换:显示)
}
alert.addAction(操作)
如果让vc=self.scene?.view?.window?.rootViewController{
vc.present(警报、动画:true、完成:nil)
}
*/
}
如果sprite2.包含(触摸位置){
打印(“你点击了紫色精灵”)
让我们现在=日期()
让howLong=now.timeIntervalSinceReferenceDate-timeStart.timeIntervalSinceReferenceDate
let REVEL=SKTRANSION.doorsOpenVertical(持续时间:0.5)
让scoreScene=scoreScene(大小:self.size,分数:howLong)
// GameScene.swift
// StackOverflow
//
// Created by Sumner on 1/17/17.
// Copyright © 2017 Sumner. All rights reserved.
//
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var cam: SKCameraNode!
var sprite = SKSpriteNode(imageNamed: "sprite")
var sprite2 = SKSpriteNode(imageNamed: "sprite2")
let pauseLabel = SKLabelNode(text: "Pause!")
/*
*
* START: NEW CODE
*
*/
let gameNode = SKNode()
var pauseMenuSprite: SKShapeNode!
let pauseMenuTitleLabel = SKLabelNode(text: "Pause Menu")
let pauseMenuContinueLabel = SKLabelNode(text: "Resume game?")
let pauseMenuToMainMenuLabel = SKLabelNode(text: "Main Menu?")
/*
*
* END: NEW CODE
*
*/
var timeStart: Date!
init(size: CGSize, difficulty: String) {
super.init(size: size)
gameDifficulty = difficulty
timeStart = Date()
/*
*
* START: NEW CODE
*
*/
pauseMenuSprite = SKShapeNode(rectOf: size)
/*
*
* END: NEW CODE
*
*/
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMove(to view: SKView) {
backgroundColor = SKColor.white
print("Game starting with \(gameDifficulty) difficulty")
// Scale Sprites
sprite.setScale(0.3)
sprite2.setScale(0.3)
sprite.position = CGPoint(x: size.width/4,y: size.height/2)
sprite2.position = CGPoint(x: size.width/4 * 3,y: size.height/2)
/*
*
* START: NEW CODE
*
*/
gameNode.addChild(sprite)
gameNode.addChild(sprite2)
addChild(gameNode)
/*
*
* END: NEW CODE
*
*/
if gameDifficulty == "hard" {
let sprite3 = SKSpriteNode(imageNamed: "sprite")
sprite3.setScale(0.3)
sprite3.position = CGPoint(x: size.width/4 * 2,y: size.height/2)
addChild(sprite3)
}
pauseLabel.fontColor = SKColor.black
pauseLabel.position = CGPoint(x: size.width/4 * 2,y: size.height/4)
addChild(pauseLabel)
}
func touchDown(atPoint pos : CGPoint) {
}
func touchMoved(toPoint pos : CGPoint) {
}
func touchUp(atPoint pos : CGPoint) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
let pausedTouchLocation = touch?.location(in: pauseMenuSprite)
if sprite.contains(touchLocation) {
print("You tapped the blue sprite")
/*
let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title: "Ok", style: .default) { action in
// Handle when button is clicked
let reveal = SKTransition.doorsOpenVertical(withDuration: 0.5)
let menuScene = MenuScene(size: self.size)
self.view?.presentScene(menuScene, transition: reveal)
}
alert.addAction(action)
if let vc = self.scene?.view?.window?.rootViewController {
vc.present(alert, animated: true, completion: nil)
}
*/
}
if sprite2.contains(touchLocation) {
print("You tapped the purple sprite")
let now = Date()
let howLong = now.timeIntervalSinceReferenceDate - timeStart.timeIntervalSinceReferenceDate
let reveal = SKTransition.doorsOpenVertical(withDuration: 0.5)
let scoreScene = ScoreScene(size: self.size, score: howLong)
self.view?.presentScene(scoreScene, transition: reveal)
}
/*
*
* START: NEW CODE
*
*/
if pauseMenuContinueLabel.contains(pausedTouchLocation!) {
pauseMenuSprite.removeFromParent()
pauseMenuSprite.removeAllChildren()
gameNode.isPaused = true
}
if pauseMenuToMainMenuLabel.contains(pausedTouchLocation!) {
let reveal = SKTransition.doorsOpenVertical(withDuration: 0.5)
let menuScene = MenuScene(size: self.size)
self.view?.presentScene(menuScene, transition: reveal)
}
if pauseLabel.contains(touchLocation) {
print("pause")
setParametersForPauseMenu(size: size)
addChild(pauseMenuSprite)
gameNode.isPaused = true
}
/*
*
* END: NEW CODE
*
*/
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
/*
*
* START: NEW CODE
*
*/
func setParametersForPauseMenu(size: CGSize) {
pauseMenuSprite.fillColor = SKColor.white
pauseMenuSprite.alpha = 0.85
pauseMenuSprite.position = CGPoint(x: size.width / 2, y: size.height / 2)
pauseMenuSprite.zPosition = 100
pauseMenuTitleLabel.fontColor = SKColor.black
pauseMenuContinueLabel.fontColor = SKColor.black
pauseMenuToMainMenuLabel.fontColor = SKColor.black
pauseMenuTitleLabel.position = CGPoint(x: 0 ,y: size.height / 2 - pauseMenuSprite.frame.size.height / 6 )
pauseMenuContinueLabel.position = CGPoint(x: 0 ,y: size.height / 2 - pauseMenuSprite.frame.size.height / 6 * 4 )
pauseMenuToMainMenuLabel.position = CGPoint(x: 0 ,y: size.height / 2 - pauseMenuSprite.frame.size.height / 6 * 5)
pauseMenuSprite.addChild(pauseMenuTitleLabel)
pauseMenuSprite.addChild(pauseMenuContinueLabel)
pauseMenuSprite.addChild(pauseMenuToMainMenuLabel)
}
/*
*
* END: NEW CODE
*
*/
}
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)
}
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
}
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