I know SpriteKit already handles pausing the game when the app enters the inactive state but what I\'m trying to do is add a SKLabelNode \"tap to resume\" when the app re-en
I think I got the problem. You should call pauseGameScene()
first. Then view?.paused
is true
. Then you can call showPauseText()
.
Hope that helps :)
So I "hacked" my solution here. Thanks to ABakerSmith
with the suggestion of setting self.speed = 0.0
, the actions were paused and the my label will appear but the physicsWorld
was still active. So my solution was to set self.speed = 0.0
AND self.physicsWorld.speed = 0.0
. When the app returns from the inactive state, I just reset self.speed = 1.0
and self.physicsWorld.speed = 1.0
. I'm sure there are other solutions to this dilemma but since SpriteKit already handles interruptions, all I really needed to do was pause the actions and the physics.
class GameScene: SKScene, SKPhysicsContactDelegate {
let tapToResume = SKLabelNode(fontNamed: "Noteworthy")
...
override func didMoveToView(view: SKView) {
...
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("pauseGameScene"), name: "PauseGameScene", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("showPauseText"), name: "ShowPauseText", object: nil)
}
func pauseGameScene() {
self.physicsWorld.speed = 0.0
self.speed = 0.0
}
func showPauseText() {
if self.physicsWorld.speed == 0.0 {
tapToResume.hidden = false
}
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
...
if self.physicsWorld.speed == 0.0 {
self.physicsWorld.speed = 1.0
self.speed = 1.0
if tapToResume.hidden == false {
tapToResume.hidden = true
}
}
}
...
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
NSNotificationCenter.defaultCenter().postNotificationName("PauseGameScene", object: self)
NSNotificationCenter.defaultCenter().postNotificationName("ShowPauseText", object: self)
}
...
}
I believe your problem was setting self.view?.paused = true
, as was pointed out by @Steve in a comment and @Linus G. in his answer. Therefore, when you tried to unhide the label, nothing happened because the view was paused.
I tried using self.paused
to pause the SKScene
instead. This solved the problems of showing the label, however it didn't actually pause the scene. This could be due to: since iOS8, SpriteKit automatically pauses your game when it enters the background and un-pauses the game when it enters the foreground. Therefore, trying to set self.paused = true
, using applicationWillResignActive
, had no effect because it was un-paused when entering the foreground.
To solve this you can observe UIApplicationWillResignActiveNotification
. Then when the application is going to resign being active, you set self.speed = 0
, which has the same effect as pausing the SKScene
. This displays the label and pauses the scene as required.
For example:
class GameScene: SKScene {
let tapToResume = SKLabelNode(fontNamed: "Noteworthy")
override func didMoveToView(view: SKView) {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: Selector("pauseScene"),
name: UIApplicationWillResignActiveNotification,
object: nil)
tapToResume.text = "tap to resume"
tapToResume.position = CGPoint(x: frame.midX, y: frame.midY)
tapToResume.fontSize = 55
tapToResume.hidden = true
self.addChild(tapToResume)
}
func pauseScene() {
self.speed = 0.0
tapToResume.hidden = false
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
// Check the label was pressed here.
if labelWasPressed {
self.speed = 1.0
tapToResume.hidden = true
}
}