问题
I have a button to pause the game on my code. What I want is that pausing the game with that button makes a message that says "Paused" to appear. However, since the scene is paused, the message does not appear.
What I have right now is a SKLabelNode with the alpha on 0.0 at the beginning and when the user pauses the game, it changes to 1.0 with fadeInWithDuration(). Then when the user presses the button again, it changes back to 0.0 with fadeOutWithDuration(). The problem is that the SKAction with fadeInWithDuration() does not run when the scene is paused.
How could I achieve this?
回答1:
The best way, one Apple also uses in "DemoBots", is to create a world node that you pause instead of the scene.
Create a worldNode property
class GameScene: SKScene {
let worldNode = SKNode()
}
add it to the scene in didMoveToView
addChild(worldNode)
and than add everything you need paused to the worldNode. This includes actions that are normally run by the scene (eg. timers, enemy spawning etc)
worldNode.addChild(someNode)
worldNode.run(someSKAction)
Than in your pause func you say
worldNode.isPaused = true
physicsWorld.speed = 0
and in resume
worldNode.isPaused = false
physicsWorld.speed = 1
You can also add an extra check in your Update function if you have stuff there that you want to ignore when paused.
override func update(_ currentTime: CFTimeInterval) {
guard !worldNode.isPaused else { return }
// your code
}
This way it's much easier to add your paused label or other UI when your game is paused because you haven't actually paused the scene. You can also run any action you want, unless that action is added to the worldNode or to a child of worldNode.
Hope this helps
回答2:
Instead of pausing the scene, you could layer some nodes your scene like this
SKScene
|--SKNode 1
| |-- ... <--place all scene contents here
|--SKNode 2
| |-- ... <--place all overlay contents here
Then when you want to pause the game, you pause only SKNode 1.
This allows node SKNode 2 to continue to run, so you can do things like have animations going, and have a button that unpauses the scene for you, without having the need to add some non Sprite Kit object into the mix.
回答3:
A quick workaround would be to pause your game after the SKLabelNode appears on screen:
let action = SKAction.fadeOutWithDuration(duration)
runAction(action) {
// Pause your game
}
Another option would be to mix UIKit and SpriteKit and inform the ViewController back that it needs show this label.
class ViewController: UIViewController {
var gameScene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
gameScene = GameScene(...)
gameScene.sceneDelegate = self
}
}
extension ViewController: GameSceneDelegate {
func gameWasPaused() {
// Show your Label on top of your GameScene
}
}
protocol GameSceneDelegate: class {
func gameWasPaused()
}
class GameScene: SKScene {
weak var sceneDelegate: GameSceneDelegate?
func pauseGame() {
// Pause
// ...
sceneDelegate?.gameWasPaused()
}
}
回答4:
So you want to pause the game AFTER the action execution has completed.
class GameScene: SKScene {
let pauseLabel = SKLabelNode(text: "Paused")
override func didMoveToView(view: SKView) {
pauseLabel.alpha = 0
pauseLabel.position = CGPoint(x: CGRectGetMaxY(self.frame), y: CGRectGetMidY(self.frame))
self.addChild(pauseLabel)
}
func pause(on: Bool) {
switch on {
case true: pauseLabel.runAction(SKAction.fadeInWithDuration(1)) {
self.paused = true
}
case false:
self.paused = false
pauseLabel.runAction(SKAction.fadeOutWithDuration(1))
}
}
}
回答5:
I would add the label with
self.addChild(nameOfLabel)
and then pause the game with
self.scene?.paused = true
This should all go in the if pauseButton is touched portion of your code.
来源:https://stackoverflow.com/questions/35536521/spritekit-run-action-while-scene-is-paused