在我使用的SpriteKit游戏中:
self.scene!.removeFromParent() let skView = self.view! as SKView skView.ignoresSiblingOrder = true var scene: PlayScene! scene = PlayScene(size: skView.bounds.size) scene.scaleMode = .AspectFill skView.presentScene(scene, transition: SKTransition.fadeWithColor(SKColor(red: 25.0/255.0, green: 55.0/255.0, blue: 12.0/255.0, alpha: 1), duration: 1.0))
从一个场景移动到另一个场景.但是我怎样才能回到原来的场景呢?使用相同的代码原则总是导致严重的崩溃..
我举了一个例子,用全局结构跟踪信息previousScene
.它也可以使用自定义属性,或者使用每个节点都有的userData.逻辑是一样的.此外,我已经删除了调试代码(调试标签代码等),因为它对于一切工作并不重要.
如果我添加几个按钮,每个链接到特定场景,示例可能会更好,但我只留下一个按钮,以尽可能缩短所有内容.
您需要了解的关于此示例的内容(您将根据您的游戏更改此规则,但逻辑是相同的 - 在实际转换之前设置previousScene):
有三个场景,WelcomeScene(默认一个),MenuScene和GameScene.
点击黑色按钮将带您进入GameScene.当前场景是GameScene时,此规则有一个例外.在这种情况下,转换将带您到previousScene.
点击黑色按钮周围的任何地方都可以转到上一个场景.首次加载WelcomeScene时,此规则有一个例外(previousScene未设置),在这种情况下转换将带您进入MenuScene.
- 在你的GameViewController中,你应该将WelcomeScene设置为默认值.否则,您应该稍微更改一下代码以处理未设置previousScene时发生的情况(就像我在toussBegan的WelcomeScene中所做的那样).
所以这些是我制定的规则,只是为了让所有这些过渡更有意义......
这是代码(BaseScene.swift):
import SpriteKit enum SceneType: Int { case WelcomeScene = 0 case MenuScene //1 case GameScene //2 } struct GlobalData { static var previousScene:SceneType? //Other global data... } class BaseScene:SKScene { let button = SKSpriteNode(color: SKColor.blackColor(), size: CGSize(width: 50, height: 50)) override func didMoveToView(view: SKView) { setupButton() } private func setupButton(){ if (button.parent == nil){ //Just setup button properties like position, zPosition and name button.name = "goToGameScene" button.zPosition = 1 button.position = CGPoint(x: CGRectGetMidX(frame), y: 100) addChild(button) } } func goToScene(newScene: SceneType){ var sceneToLoad:SKScene? switch newScene { case SceneType.GameScene: sceneToLoad = GameScene(fileNamed: "GameScene") case SceneType.MenuScene: sceneToLoad = MenuScene(fileNamed: "MenuScene") case SceneType.WelcomeScene: sceneToLoad = WelcomeScene(fileNamed:"WelcomeScene") } if let scene = sceneToLoad { scene.size = size scene.scaleMode = scaleMode let transition = SKTransition.fadeWithDuration(3) self.view?.presentScene(scene, transition: transition) } } }
每个场景(WelcomeScene,MenuScene,GameScene)都继承自BaseScene类(它是SKScene的子类).我想,没有必要解释这个问题,但可以随意问一下是否有什么东西让你困惑.这里的重要方法(由每个子类使用)是goToScene(scene:SceneType)及其参数(类型为SceneType),它告诉我们方法应该加载什么类型的场景.
SceneType只是一个包含整数的枚举...所以实际上我们不在这里使用对象,因此不用担心强引用周期.
接下来,还有其他场景(WelcomeScene.swift):
import SpriteKit class WelcomeScene:BaseScene { override func didMoveToView(view: SKView) { super.didMoveToView(view) self.backgroundColor = SKColor.darkGrayColor() } deinit {print ("WelcomeScene deinited")} override func touchesBegan(touches: Set, withEvent event: UIEvent?) { let touch = touches.first if let location = touch?.locationInNode(self){ //Give a priority to a button - if button is tapped go to GameScene let node = nodeAtPoint(location) if node.name == "goToGameScene"{ GlobalData.previousScene = SceneType.MenuScene goToScene(SceneType.GameScene) }else{ //Otherwise, do a transition to the previous scene //Get the previous scene if let previousScene = GlobalData.previousScene { GlobalData.previousScene = SceneType.WelcomeScene goToScene(previousScene) }else{ // There is no previousScene set yet? Go to MenuScene then... GlobalData.previousScene = SceneType.WelcomeScene goToScene(SceneType.MenuScene) } } } } }
为了尽可能地缩短,一切都被评论.下一个代码(MenuScene.swift):
import SpriteKit class MenuScene: BaseScene { override func didMoveToView(view: SKView) { super.didMoveToView(view) backgroundColor = SKColor.purpleColor() } deinit { print ("MenuScene deinited") //If this method isn't called, you might have problems with strong reference cycles. } override func touchesBegan(touches: Set, withEvent event: UIEvent?) { let touch = touches.first if let location = touch?.locationInNode(self){ //Give a priority to a button - if button is tapped go to GameScene let node = nodeAtPoint(location) if node.name == "goToGameScene"{ GlobalData.previousScene = SceneType.MenuScene goToScene(SceneType.GameScene) }else{ //Otherwise, do a transition to the previous scene //Get the previous scene if let previousScene = GlobalData.previousScene { GlobalData.previousScene = SceneType.MenuScene goToScene(previousScene) } } } } }
最后(GameScene.swift):
import SpriteKit class GameScene: BaseScene{ override func didMoveToView(view: SKView) { super.didMoveToView(view) self.backgroundColor = SKColor.orangeColor() } deinit {print ("GameScene deinited")} override func touchesBegan(touches: Set, withEvent event: UIEvent?) { //Here, we ignore black button because we don't want to transition to the same scene if let previousScene = GlobalData.previousScene { GlobalData.previousScene = SceneType.GameScene goToScene(previousScene) } } }
预习:
只需从头开始再读一遍规则就可以了(例如,在GameScene黑色按钮不起作用,或者在第一次启动时没有设置previousScene,所以默认情况下你将转换到MenuScene).
就是这样.希望这个对你有帮助.您可以复制并粘贴代码以对其进行测试,并根据您的需要进行改进.不过,还不确定你真的需要这个.看起来你只需要在场景之间正确转换.
提示:这里重要的是每个场景BaseScene,WelcomeScene ......都有自己的.sks文件.您可以从File-> New-> File-> Resource创建它们并对其进行适当的命名(如BaseClass.sks,WelcomeScene.sks ......)此外,维护GlobalData.previousScene
变量状态是您的工作(例如,在转型).