【发布时间】:2016-08-02 05:16:01
【问题描述】:
我如何在不重置游戏的情况下在场景之间转换,因为 didMoveToView() 被调用并重新初始化了我的所有实例变量。例如,我有一个游戏场景和一个商店场景。当我从商店场景过渡到游戏时,游戏会重置。有没有办法防止这种情况发生,或者如何在场景之间转换时保持游戏的相同状态?
【问题讨论】:
标签: swift sprite-kit skscene
我如何在不重置游戏的情况下在场景之间转换,因为 didMoveToView() 被调用并重新初始化了我的所有实例变量。例如,我有一个游戏场景和一个商店场景。当我从商店场景过渡到游戏时,游戏会重置。有没有办法防止这种情况发生,或者如何在场景之间转换时保持游戏的相同状态?
【问题讨论】:
标签: swift sprite-kit skscene
您有很多选项可以在游戏场景中保持持久状态。我列出了我使用过的两种方法。
选项 A:保持对场景的引用
当一个场景被换成一个新场景时,该场景通常会从内存中完全删除。如果您在其他地方保留场景对象的引用并呈现该引用,则不会丢失任何数据。
为了随着时间的推移保持引用(并在需要时再次呈现场景),我建议使用具有静态实例的场景呈现器类,如下所示:
class SceneCoordinator {
static var shared = SceneCoordinator()
var gameScene : GameScene?
var shopScene : ShopScene?
}
当您初始化一个GameScene 时,也将它注册到您的SceneCoordinator.shared.gameScene = self。然后,当从另一个场景过渡时,您可以呈现您存储在协调器类中的实例。
didMoveToView() 再次出现时仍会在场景中调用。您可以将所有初始化代码移动到一个单独的函数中,创建一个新的实例 var,例如 var isInitialized = false,并且仅在它为 false 时才初始化您的内容(并在初始化后将其设置为 true)。
这种方法的问题是场景对象很昂贵,这意味着您可能会因为不允许释放场景而增加大量开销。
选项 B:模型结构
更好的方法(也允许在您的应用关闭后更轻松地重新初始化场景)是创建游戏状态的数据模型,并提供一个函数来从您的模型对象创建 GameScene。
这种方法更符合 Model-View-Controller 设计模式,让你的场景和数据更加轻量。
如:
struct GameModel {
var coins : Int
}
class GameScene : SKScene {
var state : GameModel
convenience init(size: CGSize, state: GameModel) {
self.state = state
// set up scene content from state
}
// lots of fun game scene logic
func playerCollectedCoin() {
state.coins += 1
}
func moveToShopScene() {
// init a new shop scene with the state of this scene
let shop = ShopScene(size: self.view!.bounds.size, state: self.state)
(self.view as! SKView).presentScene(scene)
}
}
class ShopScene : SKScene {
var state : GameModel
convenience init(size: CGSize, state: GameModel) {
self.state = state
// set up scene content from state
}
// lots of fun shop scene logic
func playerSpentCoins(amount: Int) {
state.coins -= amount
}
func moveToGameScene() {
// init a new game scene with the updated state of this scene
let game = GameScene(size: self.view!.size, state: self.state)
(self.view as! SKView).presentScene(game)
}
}
【讨论】:
关于你的问题,我想把你的注意力集中在三个方面:
1) 您可以创建一个包含共享属性的类,而不是每次都在您的 SKScene 或 SKNode 中重复相同的共享属性(结构、变量或自定义类..)。
2) 拥有一些共享实例管理器对您的项目来说非常舒适:例如,具有您项目的所有管理器(共享实例类)的属性的游戏管理器(共享实例类)(下面的示例):
还有您的游戏属性模型,例如设置和游戏变量。
3) 如果您在场景中需要 rootNode (添加元素以暂停而不是另一个,将对象添加到同一个锚定节点,制作背景..),您可以继承自定义 @ 987654324@ 具有此属性。
一些代码显示你的项目如何出现,从 GameManager 开始:
class GameManager: NSObject {
static let sharedInstance = GameManager()
var allProducts = Products()
}
您的 GameScene 类实例可以像这样访问 GameManager 的单个实例:
class GameScene: SKScene {
let gameManager = GameManager.sharedInstance
override func didMoveToView(view: SKView) {
print("the current number of shoes is \(self.gameManager.allProducts.shoes)")
}
}
您的 ShopScene 类实例可以像这样访问同一个 GameManager 实例:
class ShopScene: SKScene {
let gameManager = GameManager.sharedInstance
override func didMoveToView(view: SKView) {
print("the current number of shoes is \(self.gameManager.allProducts.shoes)")
}
}
【讨论】: