在didBecomeActive之后iOS取消暂停游戏

时间:2016-05-06 21:10:46

标签: ios swift sprite-kit

前段时间我在didBecomeActive暂停游戏时出现问题,然后我找到了一个我认为有效的解决方案,直到现在。
我发现当我离开时,iOS会自动暂停我的游戏(所有这些),而不是终止游戏;当回来时(didBecomeActive),它会取消暂停。我的观点是暂停一个奇异的层(gameLayer),我创建了一个布尔变量和一个if条件来检查我的游戏是否暂停。

如果checkPause == false未暂停) - >当它回到游戏中时(稍后被系统取消暂停?)它会调用一个暂停功能(效果很好)
如果checkPause == true暂停) - >它会将gameLayer.paused = false(由系统取消暂停)设置为true(在离开游戏之前暂停)

基本上gameLayer在回来时没有暂停。看起来iOS在didBecomeActive功能后取消了我的游戏。


我用下面的代码制作了一个示例项目(它的所有评论都是最简单的)

如果需要,您可以下载here

import SpriteKit

class GameScene: SKScene {

    //Declarations
    var gameLayer = SKNode()
    var pauseLayer = SKNode()

    var checkPause = Bool() //checkPause == true -> gameLayer is paused | checkPause == false -> gameLayer is not paused

    var enemy = SKSpriteNode()

    var pauseButton = SKSpriteNode()
    var playButton = SKSpriteNode()



    //"Cage" objects in the screen
    func cageObjects(){

        //"caging" every object
        let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
        borderBody.friction = 0
        self.physicsBody = borderBody
    }

    //Setup
    func setupPauseButton(){

        //Pause
        pauseButton = SKSpriteNode (imageNamed: "pause")
        pauseButton.setScale(1)
        pauseButton.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 1.2)
    }
    func setupPlayButton(){

        //Play
        playButton = SKSpriteNode (imageNamed: "play")
        playButton.setScale(1)
        playButton.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 1.2)
    }
    func setupEnemy(){

        //Enemy
        enemy = SKSpriteNode(imageNamed: "enemy")
        enemy.position = CGPointMake(self.frame.width / 1, self.frame.height / 2)
        enemy.name = "enemy"
        enemy.setScale(0.5)

        enemy.physicsBody?.affectedByGravity = false
    }

    //Layers
    func createGameLayer(){

        //pauseButton
        setupPauseButton()
        gameLayer.addChild(pauseButton) //add pauseButton to gameLayer
    }
    func createPauseLayer(){

        //playButton
        setupPlayButton()
        pauseLayer.addChild(playButton) //add playButton to pauseLayer
    }

    //Spawn
    func spawnEnemy(){

        //Start spawning, moving and removing
        let spawnEnemy = SKAction.runBlock({
            () in

            //Spawn enemy
            self.setupEnemy()
            self.gameLayer.addChild(self.enemy)

            //Move left and remove when go off screen
            let frameWidth = CGFloat(self.frame.width)
            let moveEnemy = SKAction.moveByX(-frameWidth - 50, y: 0, duration: NSTimeInterval(0.0028 * frameWidth)) //duration: faster or slower
            let removeEnemy = SKAction.removeFromParent()

            var moveAndRemove = SKAction()
            moveAndRemove = SKAction.sequence([moveEnemy, removeEnemy])

            self.enemy.runAction(moveAndRemove)
        })

        //Spawn enemy each 2 seconds
        let spawnEnemyDuration = SKAction.repeatActionForever(SKAction.sequence([spawnEnemy, SKAction.waitForDuration(2.0)]))
        gameLayer.runAction(spawnEnemyDuration)
    }

    override func didMoveToView(view: SKView) {
        /* Setup your scene here */

        print ("didMoveToView")

        registerAppTransitionObservers()

        cageObjects()

        checkPause = false

        createGameLayer()
        createPauseLayer()

        self.addChild(gameLayer)

        spawnEnemy()
    }

    //Game states
    func pauseState(){

        //Pause game
        pauseButton.hidden = true //hide pauseButton
        gameLayer.paused = true //pause gameLayer
        checkPause = true //game is paused

        self.addChild(pauseLayer) //add pauseLayer
    }
    func playState(){

        pauseLayer.removeFromParent() //remove pauseLayer

        //Resume game
        checkPause = false //game is not paused
        gameLayer.paused = false //unpause gameLayer
        pauseButton.hidden = false //show pauseButton
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
       /* Called when a touch begins */

        //When touch buttons/screen
        for touch in touches{

            let location = touch.locationInNode(self)
            let node = nodeAtPoint(location)

            if node == pauseButton{
                pauseState()
            }
            else if node == playButton{
                playState()
            }
        }
    }



    //Functions from AppDelegate
    func registerAppTransitionObservers(){
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(GameScene.applicationDidBecomeActive), name: UIApplicationDidBecomeActiveNotification, object: nil)
    }

    //Just launched
    func applicationDidBecomeActive(){
        print("DidBecomeActive")

        //gameLayer unpausing problem solving attempt
        if checkPause == true{
            gameLayer.paused = true
        }
        //Pause when game is not paused and user leave the screen OR when game is launched
        else if checkPause == false{
            pauseState()
        }
    }
}

1 个答案:

答案 0 :(得分:1)

现在我有你的来源,我看到了你的问题。

您需要保留暂停状态:

class GameScene : SKScene
{
    ...
    override var paused: Bool
    {
        get{
            return super.paused;
        }
        set{
            let value = self.gameLayer.paused
            super.paused = newValue;
            self.gameLayer.paused = value;

        }

    }
}

出于某种原因,暂停的场景决定取消暂停其下的所有节点

此外,您应该在离开应用时暂停游戏,而不是在您回来时暂停游戏。

//Functions from AppDelegate
func registerAppTransitionObservers(){
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(GameScene.applicationWillResign), name: UIApplicationWillResignActiveNotification, object: nil)
}

func applicationWillResign(){
    print("WillResignActive")
    pauseState()
}

你可以摆脱那个检查暂停变量,即多余的膨胀代码。