【问题标题】:dismiss SKScene in SpriteKit and Swift在 SpriteKit 和 Swift 中关闭 SKScene
【发布时间】:2014-12-22 15:29:36
【问题描述】:

当我的游戏暂停时,我设法打开了另一个信息/信用/设置视图

let block = SKAction.runBlock {
    let myScene = CreditsScene(size: self.size)
    myScene.scaleMode = self.scaleMode
    self.view?.presentScene(myScene)
}
self.runAction(block)

CreditsScene 打开时,我可以点击场景返回暂停的游戏。 但是,无论我如何尝试,我都无法回头:(

目前我做的最好的就是

let block = SKAction.runBlock {
    let myScene = GameScene(size: self.size)
    myScene.scaleMode = self.scaleMode
    self.view?.presentScene(myScene)
}
self.runAction(block)

在我看来,这会打开一个新的 GameScene 而不是之前的。我也尝试过removeFromParentpresentScene(nil),但它们都不起作用。

您还有其他更好的想法吗? 谢谢

【问题讨论】:

    标签: ios swift sprite-kit skscene


    【解决方案1】:

    您正在展示一个新的GameScene,因为您正在创建一个新的GameScene。如果您想保留您正在使用的 GameScene 实例并返回到它,您需要展示它。要么,要么您需要一种方法让您的 GameScene 类保存和恢复其状态,以便可以恢复它的新实例以复制旧实例中发生的任何事情。


    对于第一个选项,您可以这样做:

    // in GameScene
    let block = SKAction.runBlock {
        let credits = CreditsScene(size: self.size)
        credits.returnToScene = self    // add this property to CreditsScene
        credits.scaleMode = self.scaleMode
        self.view?.presentScene(credits)
    }
    self.runAction(block)
    
    // in CreditsScene
    let block = SKAction.runBlock {
        self.view?.presentScene(self.returnToScene)
    }
    self.runAction(block)
    

    在这里,您将对当前GameScene 的引用传递给您的CreditsScene,以便CreditsScene 知道完成后要返回的GameScene。或者,您可以将对当前 GameScene 的引用存储在某个全局位置(至少相对于场景),例如视图控制器。


    对于另一个选项,您需要确保您的 GameScene 类中的所有状态(或至少对玩家有意义的所有状态)都可以保存和恢复:当前得分、当前玩家位置,敌人在哪里,他们在做什么,等等......无论你的游戏做什么。 SpriteKit 类已经支持NSCoding,因此这是处理保存/恢复的好方法——只需确保您的任何自定义子类(如GameScene)对它们具有的任何状态进行编码。

    然后,您可以在转出时存档您的 GameScene,并在您准备返回时从该存档中恢复。看起来像这样:

    // in GameScene
    let block = SKAction.runBlock {
        let credits = CreditsScene(size: self.size)
        credits.returnToScene = self    // add this property to CreditsScene
        credits.scaleMode = self.scaleMode
    
        let sceneData = NSKeyedArchiver.archivedDataWithRootObject(self)
        sceneData.writeToFile(savedGamePath, atomically: true)
    
        self.view?.presentScene(credits)
    }
    self.runAction(block)
    
    // in CreditsScene
    let block = SKAction.runBlock {
        if let game = NSKeyedUnarchiver.unarchiveObjectWithFile(savedGamePath) {
            self.view?.presentScene(game)
        }
    }
    self.runAction(block)
    

    (假设savedGamePath 是两个类都可以访问的常量。)


    顺便说一句,如果您在此处使用 SKAction.runBlock 反映了您游戏中的实际情况(而不是为了这个 SO 问题而简化您的代码),那么它是多余的。您无需为要立即运行的代码创建runBlock 操作。因此,除非您实际上需要隐藏该操作以供以后运行,否则您可以将我上面的第一个解决方案简化为如下所示:

    // in GameScene
    let credits = CreditsScene(size: self.size)
    credits.returnToScene = self    // add this property to CreditsScene
    credits.scaleMode = self.scaleMode
    self.view?.presentScene(credits)
    
    // in CreditsScene
    self.view?.presentScene(self.returnToScene)
    

    【讨论】:

    • 感谢您的第一个选项,我做到了。无论如何,我会尝试第二个,只是为了学习。当然非常感谢,你说的都很清楚!
    • 你能解释一下为什么如果我放置一个转换,如果我不使用它会出现不同的行为。换句话说,我在游戏暂停且敌人静止时打开了第二个场景。但是,如果我在返回时放置一个过渡,游戏仍然会暂停,但敌人会移动。
    猜你喜欢
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-26
    • 2020-04-18
    • 1970-01-01
    相关资源
    最近更新 更多