应用程式启用后,让场景中的粒子保持暂停状态

时间:2019-01-31 11:55:16

标签: swift sprite-kit

让我在开始回答这个问题时先说我知道有人问过几次,但是最受好评的帖子here是在2014年,最热门的答案似乎不再起作用。

问题

在我的游戏中,我所有的“移动”节点都作为pauseNode的子节点。当按下暂停按钮或播放器离开应用程序时,将调用pauseScene()

func pauseScene() {
    self.node.speed = 0
    self.physicsWorld.speed = 0
    self.node.isPaused = true
}

这将暂停所有精灵节点和发射器节点。如果应用程序从背景状态转换为前景状态,则可以使子画面节点保持暂停状态,但是粒子发射器似乎可以恢复动画。

当前解决方案

我通过在应用程序启动一段时间后触发pauseScene()解决了这个问题。

override func didMove(to view: SKView) {
     NotificationCenter.default.addObserver(self, selector: #selector(GameScene.applicationDidBecomeActive(notification:)), name: NSNotification.Name.UIApplicationDidBecomeActive, object: app)
}

@objc func applicationDidBecomeActive(notification: NSNotification) {
    NSDelay(0.01) {
        pauseScene()
    }
}

func NSDelay(_ delay:Double, closure:@escaping ()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}

目标

虽然此解决方案可以暂停粒子,但是它并不是完美的,因为可以看到它们在瞬间移动以再次暂停它们(这是实际上重新暂停它们的最短延迟)。

因此,在阅读了我上面链接的文章之后,我尝试按照建议的方法在SKView子类中重写applicationDidBecomeActive(),但无法调用该方法。如果可能的话,我想首先阻止这些粒子。谢谢

1 个答案:

答案 0 :(得分:0)

所以,已经过去了一天多,我找到了一个更好的解决方案。 this帖子中的评论建议使用一个变量来记录场景的状态,并与暂停/播放功能一起对其进行更新:

var sceneIsPaused = false

func pauseScene() {
    self.node.speed = 0
    self.physicsWorld.speed = 0
    self.node.isPaused = true

    sceneIsPaused = true
}

func playScene() {
    self.node.speed = 1
    self.physicsWorld.speed = 1
    self.node.isPaused = false

    sceneIsPaused = false
}

然后,重写SKView的update方法并检查该变量的状态。如果场景的的暂停,暂停。这意味着如果场景自动取消暂停,它将重新暂停下一帧。这比设定的延迟更快和更清洁的:

override func update(_ currentTime: TimeInterval) {
    if (sceneIsPaused == true) {
        self.node.speed = 0
        self.physicsWorld.speed = 0
        self.node.isPaused = true
    }
}