Search code examples
swiftskviewpausegamecontroller

Keeping the game paused after app become active?


It is my first post on this forum and I apologize in advance if I am doing something not in the right way ! :)

I am making an iphone game with Swift & SpriteKit and I am currently facing a problem. When my app is going to background it calls a function pause (cf. below) but it automatically unpause when the game resumes.

I have seen this very interesting post : Spritekit - Keep the game paused when didBecomeActive (and How to keep SpriteKit scene paused when app becomes active?) but I am stuck.

I don't know how to implement the new SKView class as my View is configured as shown in the below code...

This is how my application works :

class GameViewController: UIViewController {

var scene: GameScene!

override func viewDidLoad() {
    super.viewDidLoad()

    // Configure the View
    let SkView = view as! SKView
    SkView.multipleTouchEnabled = true

    // Create and configure the scene
    scene = GameScene(size: SkView.bounds.size)
    scene.scaleMode = .AspectFill

    // Present the scene
    SkView.presentScene(scene)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("PauseWhenBackGround:"), name:"PauseWhenBackGround", object: nil)
}

func PauseWhenBackGround(notification : NSNotification) {
    if scene.Pausing == false{
        scene.Pause()
    }
}

I've tried the following :

I added a new class which is :

class GameSceneView : SKView {      
    func CBApplicationDidBecomeActive() {
    }
}

Then, I tried to set my view as let SkView = view as! GameSceneView but I got an error saying that I cannot cast the view to MyProjectName.GameSceneView()... I also tried the following : let SkView! = GameSceneView() as GameSceneView! but I end up with a gray background scene...

Does anyone knows how I can implement the new SKView class to prevent the CBApplicationDidBecomeActive() bug from happening so that the game does not unpause when becoming active ?

Thank you very much in advance ! :)


Solution

  • I think a better way is instead of pausing the whole scene you could create a worldNode in your GameScene and add all the sprites that need to be paused to that worldNode. Its better because if you pause the scene you cannot add pause menu nodes or use touches began etc. It basically gives you more flexibility pausing a node rather than the whole scene.

    First create the world node (make global property if needed)

     let worldNode = SKNode()
     addChild(worldNode)
    

    Than add all the sprites you need paused to the worldNode

     worldNode.addChild(sprite1)
     worldNode.addChild(sprite2)
    

    Create an enum for your different game states

    enum GameState {
        case Playing
        case Paused
        case GameOver
        static var current = GameState.Playing
    }
    

    Than make a pause func in your game scene

     func pause() {
         GameState.current = .Paused
         //self.physicsWorld.speed = 0 // in update
         //worldNode.paused = true     // in update
    
         // show pause menu etc
     }
    

    And call it like you did above using NSNotification or even better using delegation.

    I prefer this method way more than pausing the scene from the gameViewController and also pausing the whole scene.

    Create a resume method

     func resume() {
            GameState.current = .Playing
            self.physicsWorld.speed = 1
            worldNode.paused = false  
    
            // remove pause menu etc
     }
    

    and finally add this to your update method

    override func update(currentTime: CFTimeInterval) {
    
      if GameState.current == .Paused { 
          self.physicsWorld.speed = 0
          worldNode.paused = true
    }
    

    Spritekit sometimes tends to resume the game when the app becomes active again or when an alert such as for in app purchases is dismissed. To avoid this I always put the code to actually pause the game in the update method.

    Hope this helps.