SpriteKit:当场景暂停时运行操作。

时间:2021-09-14 10:40:46

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.

我现在拥有的是一个SKLabelNode,在开始时alpha值为0.0,当用户暂停游戏时,fadeInWithDuration()将其更改为1.0。然后,当用户再次按下按钮时,fadeOutWithDuration()将其更改为0.0。问题是当场景暂停时,使用fadeInWithDuration()的SKAction不会运行。

How could I achieve this?

我如何做到这一点?

5 个解决方案

#1


11  

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

创建一个worldNode属性

class GameScene: SKScene {

    let worldNode = SKNode()
}

add it to the scene in didMoveToView

将它添加到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。这包括通常由场景运行的操作。计时器,敌人产卵等)

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.

这样,在游戏暂停时添加暂停标签或其他UI就容易得多,因为实际上还没有暂停场景。您还可以运行任何您想要的操作,除非该操作被添加到worldNode或worldNode的子节点。

Hope this helps

希望这有助于

#2


3  

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.

然后,当您想暂停游戏时,您只需暂停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.

这允许节点SKNode 2继续运行,因此您可以做一些事情,比如让动画运行,并有一个按钮为您取消场景的暂停,而不需要在混合中添加一些非Sprite Kit对象。

#3


2  

A quick workaround would be to pause your game after the SKLabelNode appears on screen:

一个快速的解决方案是在SKLabelNode出现在屏幕上后暂停游戏:

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.

另一个选项是混合UIKit和SpriteKit并通知ViewController需要显示这个标签。

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


1  

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


0  

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.

这些都应该放在if pauseButton中。

#1


11  

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

创建一个worldNode属性

class GameScene: SKScene {

    let worldNode = SKNode()
}

add it to the scene in didMoveToView

将它添加到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。这包括通常由场景运行的操作。计时器,敌人产卵等)

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.

这样,在游戏暂停时添加暂停标签或其他UI就容易得多,因为实际上还没有暂停场景。您还可以运行任何您想要的操作,除非该操作被添加到worldNode或worldNode的子节点。

Hope this helps

希望这有助于

#2


3  

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.

然后,当您想暂停游戏时,您只需暂停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.

这允许节点SKNode 2继续运行,因此您可以做一些事情,比如让动画运行,并有一个按钮为您取消场景的暂停,而不需要在混合中添加一些非Sprite Kit对象。

#3


2  

A quick workaround would be to pause your game after the SKLabelNode appears on screen:

一个快速的解决方案是在SKLabelNode出现在屏幕上后暂停游戏:

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.

另一个选项是混合UIKit和SpriteKit并通知ViewController需要显示这个标签。

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


1  

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


0  

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.

这些都应该放在if pauseButton中。