What's the cleanest way to call a method from one SKScene to another in Swift?

萝らか妹 提交于 2019-12-08 03:51:17

问题


So I got in my game 3 different scenes: MenuScene, GameScene and GameOverScene.

I would like to know how I can get the score variable located in GameScene from GameOverScene so I can show it up there after the player loses.

So in GameScene, I created this simple getter:

func getScore() -> Int {
   return self.score
}

But if I try to do GameScene.getScore() from a different Scene I get an error.

Tried using "class" before func

class func getScore() -> Int {
   return self.score
}

But that also gives me an error from GameScene saying:

"Instance member 'score' cannot be used on type GameScene"

So how's the best way to do it? I don't want to create a global variable for this, it would be ugly.


回答1:


This is quite easy actually. When you segue to the new scene, you can also pass in a variable with it... Here is an example.

GameOverScene.swift

var score:Int = 0

GameScene.swift

var score:Int = THE USERS SCORE    

func segue(){
    let gameScene = GameOverScene(size: self.size)
        gameScene.score = score
        let transition = SKTransition.doorsCloseHorizontalWithDuration(0.5)
        gameScene.scaleMode = SKSceneScaleMode.AspectFill
        self.scene!.view?.presentScene(gameScene, transition: transition)
}



回答2:


You need to keep an instance of GameScene in your MenuScene class (recommended). Alternatively, you can store the score in a global storage medium.

To enter the game scene, you need to create it first, right?

let scene = SKScene(fileNamed: "blah blah blah")
view.presentScene(scene)

Now instead of creating the scene and assigning it to a local variable, you assign it to a class level variable.

var gameScene: GameScene?

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if (...) {
        gameScene = SKScene(fileNamed: "blah blah blah")
        view.presentScene(gameScene!)
    }
}

Then, when appropriate, you can access the score like this:

gameScene.getScore()

Another way is to use NSUserDefaults, but you don't seem to like it.

The final way that I can think of is to use static variables. You put all the stuff that you need to pass between the two scenes in a class as static variables. The disadvantage of this is that unless you declare the class private and put both scenes and the class in the same file, others classes can access and change the variables. This reduces maintainability.

Explicit getters are not needed in Swift, btw.




回答3:


There are many ways to achieve what do you want to do. You could use a manager class , a shared instance to maintain your game variables.

Why this choice?

Because you will want to save your values or your profile or you will want to reset all the game progress, because you will want to select the old 2nd level when you have unlocked the 18th level, or repeat a failed level without accumulating values. It's fast to do it and you can handle separately your common game variables (it seems that I'm selling pots in an advertisement..)

class Settings: NSObject { // NSCoding in case you want to save your data
    var score: Int = 0
    func encodeWithCoder(aCoder: NSCoder!) {
        aCoder.encodeInteger(score, forKey: "score")
    }
    init(coder aDecoder: NSCoder!) {
        score = aDecoder. decodeIntegerForKey("score") 
    }
    override init() {
        super.init()
        // do whatever you want to initializing your settings
    }
}
class GameManager: NSObject {
    static let sharedInstance = GameManager()
    var settings : Settings! = Settings()
}
class MenuScene: SKScene {
    let gameManager = GameManager.sharedInstance
    override func didMoveToView(view: SKView) {
       print("the current score is \(self.gameManager.settings.score)")
    } 
}
class GameScene: SKScene {
    let gameManager = GameManager.sharedInstance
    override func didMoveToView(view: SKView) {
       print("the current score is \(self.gameManager.settings.score)")
    } 
}
class GameOverScene: SKScene {
    let gameManager = GameManager.sharedInstance
    override func didMoveToView(view: SKView) {
       print("the current score is \(self.gameManager.settings.score)")
    } 
}


来源:https://stackoverflow.com/questions/38668801/whats-the-cleanest-way-to-call-a-method-from-one-skscene-to-another-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!