SpriteKit:如何识别用户来自的前一个场景?

时间:2017-01-06 01:19:51

标签: sprite-kit swift3

我有一个带有设置场景按钮的GameOver场景。 (下面显示的代码)我想在MainMenu场景上添加一个按钮来执行相同操作,将用户发送到“设置”场景,但我只想在“设置”场景中选择一个“后退”按钮。我假设这可以用IF语句完成。如果用户来自A场景,则移动到B else,如果用户来自X场景,则移动到Y场景。

如何在SpriteKit中告诉用户来自哪个场景?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    for touch: AnyObject in touches {

        let pointOfTouch = touch.location(in: self)

        let nodeUserTapped = atPoint(pointOfTouch)

        if nodeUserTapped.name == "BackButton" {

            let sceneToMoveTo = SKScene(fileNamed: "GameOverScene")
            let gameTransition = SKTransition.fade(withDuration: 0.5)
            self.view!.presentScene(sceneToMoveTo!, transition: gameTransition)

        }

    }

}

2 个答案:

答案 0 :(得分:5)

在这种情况下,您可以采用各种解决方案来实现您的目标。 我想向您展示两个示例,一种快速简单的方法和一种更自定义的方式。

1: - 您可以使用下一个场景的userData实例属性来存储当前场景,例如:

sceneToMoveTo.userData = NSMutableDictionary()
sceneToMoveTo.userData?.setObject("MenuScene", forKey: "previousScene" as NSCopying)

当你在下一个场景中时,你可以向前一个场景的NSMutableDictionary询问:

guard let previousValue = self.userData?.value(forKey: "previousScene") else { return }
switch previousValue as! String {
case "MenuScene":
   //do whatever you want if the previous scene was MenuScene
default:
   break
}

2: - 您可以构建一个枚举,其中包含您要移动的场景列表。

之后,每个场景都包含一个简单的var来存储前一个场景:它的默认值是.None,但是你应该在调用新场景时填充它。当你到达SettingsScene并按下你的后退按钮时,你可以向这个previousScene var询问前一个场景,并通过一个开关语句决定去哪里。

// GAMEOVER SCENE
import SpriteKit
enum Scenes : Int {
    case MainMenu = 0
    case Settings = 1
    case GameOver = 2
    case None = 3
}
class GameOver: SKScene {
    var previousScene:Scenes = .None
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch: AnyObject in touches {
            let pointOfTouch = touch.location(in: self)
            let nodeUserTapped = atPoint(pointOfTouch)
            if nodeUserTapped.name == "settingsBtn" {
                if let sceneToMoveTo = SKScene(fileNamed: "SettingsScene") {
                    let gameTransition = SKTransition.fade(withDuration: 0.5)
                    (sceneToMoveTo as! SettingsScene).previousScene = .GameOver
                    self.view?.presentScene(sceneToMoveTo, transition: gameTransition)
                }   
            }     
        }
    }
}
// SETTINGS SCENE
import SpriteKit
class SettingsScene: SKScene {
    var previousScene:Scenes = .None
    override func didMove(to view: SKView) {
        print("Current scene loaded: \(type(of:self))")
        print("Previous scene was: \(previousScene)")
        let label = SKLabelNode.init(text: "BackButton")
        addChild(label)
        label.position = CGPoint(x:self.frame.midX,y:self.frame.midY)
        label.name = "backBtn"
    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch: AnyObject in touches {
            let pointOfTouch = touch.location(in: self)
            let nodeUserTapped = atPoint(pointOfTouch)
            if nodeUserTapped.name == "backBtn" {
                switch previousScene {
                case .MainMenu: // go back to menu
                    if let sceneToMoveTo = SKScene(fileNamed: "MenuScene") {
                        let gameTransition = SKTransition.fade(withDuration: 0.5)
                        (sceneToMoveTo as! MenuScene).previousScene = .Settings
                        self.view?.presentScene(sceneToMoveTo, transition: gameTransition)
                    }
                    break
                case .GameOver: // re-launch a new game
                    print("The game was ended")
                    if let sceneToMoveTo = SKScene(fileNamed: "GameScene") {
                        let gameTransition = SKTransition.fade(withDuration: 0.5)
                        (sceneToMoveTo as! GameScene).previousScene = .Settings
                        self.view?.presentScene(sceneToMoveTo, transition: gameTransition)
                    }
                default:
                    break
                }
            }

        }
    }
}
//MENU SCENE
import SpriteKit
class MenuScene: SKScene {
    var previousScene:Scenes = .None
    override func didMove(to view: SKView) {
        print("Current scene loaded: \(type(of:self))")
        print("Previous scene was: \(previousScene)")
    }
}

答案 1 :(得分:1)

userData在这里是你的朋友,它是一个可以在任何类型的SKNode上找到的字典。您需要做的就是将当前场景存储到userData中,然后进行转换。这将使您当前的场景保持在内存中。由于您当前的场景在内存中并且不是新场景节点树的一部分,因此不会在其上调用更新方法。基本上你有一个冻结的场景状态。然后,当您准备好返回场景时,只需将实例从用户数据中拉出并显示即可。中提琴,你之前离开时已经过渡到你的场景。

基本上,如果您希望场景从中断处继续,请执行以下操作:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    for touch: AnyObject in touches {

        let pointOfTouch = touch.location(in: self)

        let nodeUserTapped = atPoint(pointOfTouch)

        if nodeUserTapped.name == "SettingButton" {

            let sceneToMoveTo = SKScene(fileNamed: "SettingScene")
            sceneToMoveTo.userData = ["previousScene":self.scene]

            let gameTransition = SKTransition.fade(withDuration: 0.5)
            self.view!.presentScene(sceneToMoveTo!, transition: gameTransition)
        }
    }
}

然后,在您想要返回上一个场景的任何时刻,只需添加以下内容。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    for touch: AnyObject in touches {

        let pointOfTouch = touch.location(in: self)

        let nodeUserTapped = atPoint(pointOfTouch)

        if nodeUserTapped.name == "BackButton" {

           if let userData = self.userData, let previousScene = userData["previousScene"] as? SKScene
           {
                let gameTransition = SKTransition.fade(withDuration: 0.5)
                self.view!.presentScene(previousScene, transition: gameTransition)
           }
        }
    }
}