Quicksillver Quicksillver - 1 month ago 16
iOS Question

Unable to Update an SKLabel Node using Swift 3 on button press

I'm trying to make a small game using SpriteKit. ( Xcode 8 and Swift 3 for iOS 10 )

I want to let the user pause the game when he touches the Pause text label. When he does that, I want to pause the game and change the label text to Unpause.

Below is my code for that part.

if ( pauseTextLabel.contains(touchLocation!)){
gameLoopPaused = !gameLoopPaused;
if ( pauseTextLabel.text == "Pause" ){
// pauseTextLabel.text = "Unpause";
pauseTextLabel = SKLabelNode(fontNamed: gameData.fontName);
initLabel(label: pauseTextLabel, gameData: gameData, text: "Unpause", pos: CGPoint(x: 3 * self.size.width/4 , y: self.size.height - 50 ) );
self.addChild(pauseTextLabel);
runPauseAction();
} else {
pauseTextLabel.text = "Pause";
runUnpauseAction();
}
}


I tried doing this first, It didn't work.

if ( pauseTextLabel.contains(touchLocation!)){
gameLoopPaused = !gameLoopPaused;
if ( pauseTextLabel.text == "Pause" ){
pauseTextLabel.text = "Unpause";
runPauseAction();
} else {
pauseTextLabel.text = "Pause";
runUnpauseAction();
}
}


I added a break point just before that block and this block shows no messages in the console. The game is being paused and I am able to resume it. However the only thing not working is the display text updating. I tried to remove it and add it to the view. It didn't work.

Any help or hints what went wrong is really appreciated.

Edit:
I modified the touchesBegan as suggested. I am including my runPauseAction() to provide more information in case that matters.

private func runPauseAction(){
print(#function);

//self.pauseTextLabel.text = "Resume";
self.view?.isPaused = true;
self.physicsWorld.speed = 0.0;

}

Answer

Are you pausing the whole scene in

runPauseAction()

?

If you pause the whole scene than add the unpause method before the text label change.

runUnpauseAction()
pauseTextLabel.text = "Pause"

I would reccommend you create a worldNode in your gameScene for pausing.

let worldNode = SKNode()

than add it to the scene

addChild(worldNode)

and than add everything you need paused to that worldNode

worldNode.addChild(SOMENODE)
worldNode.addChild(SOMENODE2)

Than when you pause you call this

 worldNode.isPaused = true
 physicsWorld.speed = 0

and when you resume you call this

 worldNode.isPaused = false
 physicsWorld.speed = 1

This is a nicer way to pause your game, apple also does this in DemoBots. It also gives you more flexibility doing stuff, like overlaying menu nodes, when the game is paused.

I would also write your touches method like this.

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self)
        let node = atPoint(location)

        if node == pauseTextLabel {
            if !gameLoopPaused {
                gameLoopPaused = true
                pauseTextLabel.text = "Unpause"
                runPauseAction()
            } else {
                runUnpauseAction()
                gameLoopPaused = false
                pauseTextLabel.text = "Pause"
            }
        }
    }
}

If you are using the pausing skView way and you still have issues try using an SKAction with delay to call the pause code like 0.1 seconds after changing the text label.

Hope this helps