Reputation: 1935
While my game is paused I managed to open another view for info/credits/settings as
let block = SKAction.runBlock {
let myScene = CreditsScene(size: self.size)
myScene.scaleMode = self.scaleMode
self.view?.presentScene(myScene)
}
self.runAction(block)
When the CreditsScene
opens I can tap on the scene to go back to the paused game.
However no matter how I try I cannot go back :(
At the moment the best I did is like
let block = SKAction.runBlock {
let myScene = GameScene(size: self.size)
myScene.scaleMode = self.scaleMode
self.view?.presentScene(myScene)
}
self.runAction(block)
which in my opinion opens a NEW GameScene and not the previous one. I also tried removeFromParent
, presentScene(nil)
, but none of them work.
Do you have other better ideas? Thanks
Upvotes: 2
Views: 1734
Reputation: 126167
You're presenting a new GameScene
because you're creating a new GameScene
. If you want to keep the GameScene
instance you were using and return to it, you'll need to present that instead. Either that, or you'll need a way for your GameScene
class to save and restore its state, so that a new instance of it can be restored to replicate whatever was going on in the old instance.
For the first option, you could do something like this:
// 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)
Here, you're passing a reference to the current GameScene
to your CreditsScene
, so that the CreditsScene
knows what GameScene
to return to once it's done. Alternatively, you could store a reference to the current GameScene
in some place that's global (relative to the scenes, at least), like a view controller.
For the other option, you'll need to make sure that all the state in your GameScene
class (or at least all the state that's meaningful to the player) can be saved and restored: current score, current player position, where the enemies are and what they're doing, etc... whatever your game does. SpriteKit classes already support NSCoding
, so this is a good way to handle saving/restoring — just make sure that any custom subclasses of yours (like GameScene
) encode whatever state they have.
Then, you can archive off your GameScene
when transitioning away, and restore from that archive when you're ready to return. That'd look something like this:
// 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)
(This presumes savedGamePath
is a constant accessible to both classes.)
By the way, if your use of SKAction.runBlock
here reflects what's actually in your game (as opposed to a simplification of your code for purposes of this SO question), it's redundant. You don't need to create a runBlock
action for code you're going to run immediately. So, unless you actually need to stash that action for running later, you can simplify my first solution above down to something like this:
// 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)
Upvotes: 4