Pausing and Playing SpriteKit Game in Swift - ios

How do I pause and resume a game in SpriteKit in a single Scene Game (gameScene)?
addChild(pauseText)
self.runAction(SKAction.runBlock(self.pauseGame))

To pause a game from the view controller, you should call gameView.paused = true (where gameView is an SKView).
To pause a game from the scene itself, you should call physicsWorld.speed = 0. To un-pause the game, call physicsWorld.speed = 1.

Related

Scenekit gesture recognizer and overlaySKScene touches

Currently working on a game with scene kit in swift. I've got a joystick added to a SKScene, which is then attached to my scene kit game scene. Typical HUD overlay for controls.
let hudScene = SKScene(size: view.frame.size)
scnView.overlaySKScene = hudScene
I have also added a joystick to hudScene and want to add some buttons. Now, all of this works fine until I add a gesture recognizer to my main game scene. Once I do, all tap interaction with the hudScene is completely ignored. Even if I tap on the joystick and log what node was tapped at that location, it gives me the node in my game scene and completely ignores the nodes in hudScene.
Can anybody provide any insight into why this is happening?
For reference, the touch events for the joystick are implemented from this library, and my gesture recognizer is implimented like this:
let touchDownRec = UILongPressGestureRecognizer(target: self, action: #selector(didTouchDown(_:)) )
touchDownRec.minimumPressDuration = 0
touchDownRec.numberOfTouchesRequired = 1
scnView.addGestureRecognizer(touchDownRec)
I had the same problem... you have to replace the touchesBegan with a TapGesture, or replace the UILongPressGestureRecognizer with touchesEnded, but is more precise the first option.

SpriteKit - Objective C - camera Constraints

I am currently working a spriteKit 2D game using Objective C. It's a tile based game similar to superMario. I am having a problem with my Camera.
I added a camera that is following my player, but when the player gets closer to the edges of the scene, the camera goes out of bounds. Setting up the camera was easy.
-(void)didMoveToView:(SKView *)view {
//add Camera
mainCamera = [SKCameraNode node];
self.camera = mainCamera;
}
then in :
-(void)update:(NSTimeInterval)currentTime {
[super update: currentTime];
mainCamera.position = avatar.position;
}
However i need to add Constraints so that the camera stays within the container of the scene.
Add a physics body to the camera, make it a rectangle the size of the scene.
Since you are doing your update of the camera in the beginning of the update, the physics engine will move the camera prior to being drawn.
make sure you set the restitution to 0 to avoid bouncing

Pause Sprite Kit game with physics doesn't work correctly on iOS 9

I have a problem in pausing a sprite kit game with physics. The game contains a ball which moves in the SpriteScene and has the following parameters:
self.ball.physicsBody.friction = 0;
self.ball.physicsBody.linearDamping = 0;
self.ball.physicsBody.restitution = 1.0f;
self.ball.physicsBody.affectedByGravity = NO;
self.ball.physicsBody.usesPreciseCollisionDetection = YES;
The problem is that when I pause the game, I call these methods:
self.scene.physicsWorld.speed = 0;
self.ball_velocity = self.ball.physicsBody.velocity;
self.ball.physicsBody.velocity = CGVectorMake(0, 0);
self.ball.speed = 0;
self.ball.physicsBody.dynamic = NO;
[self.scene.view setPaused:YES];
and when resume, call these:
self.scene.physicsWorld.speed = 1;
self.ball.physicsBody.velocity = self.ball_velocity;
self.ball.physicsBody.dynamic = YES;
self.ball.speed = 1;
[self.scene.view setPaused:NO];
This stops the ball animation, but when resume, the ball position is changed and it seems if that was moving during the pause duration.
BTW, it works fine on iOS 8 but on iOS 9 it always fails.
Any suggestions ?!!
After chatting, we have come to the conclusion that between iOS8 and iOS9, Apple has done a change that pausing the scene now pauses the update loop. Since the update loop is being paused, the change in time is not being calculated correctly. What is now happening, is the change in time will be the time at unpause - the time at pause, simulating a lag state. The velocity will take the math into effect, and move objects based on this difference in time. To combat this issue, just make a parent node that will house all of your scenes's objects, and pause the parent. This will allow the update to still be called, thus allowing the change in time to stay consistent with the frame rate.

Pause and resume animation in the same keyframe

Is it possible to pause animation of SCNNode (animaton with model from .dae collada) and then resume in the same keyframe which it was paused?
Will using the isPaused property on the SCNNode work for your needs?
Example:
self.childNode.isPaused = true

pause spritekit scene and show "paused" label

I want to show a "paused" SKLabelNode when someone clicks on the screen and therefore pauses the sprite kit game.
So I have in touchesBegan ->
[self.pausedLabel setHidden:!self.pausedLabel.hidden];
[self.scene.view setPaused:!self.scene.view.paused];
The Game is paused correctly but the SKLabelNode is not shown (scene not rendered before paused?!)
If I add a NSTimer for pausing the scene the label is shown, but then the game continues for that timer-time.
Does anyone have a better solution for this?
Thanks in advance
I would use SKAction for this. You can use +runBlock: to add the code related to hiding the label, and then use the -runAction method with the completion handler to pause the scene. The runBlock: method may return immediately, but this way, the screen manages to update before the scene is paused.
SKAction *action = [SKAction runBlock:^{
[self.pausedLabel setHidden:!self.pausedLabel.hidden];
}];
[self.pausedLabel runAction:action completion:^{
[self.scene.view setPaused:!self.scene.paused];
}];
Just use a state ivar to determine if the scene should update its content or not.
When you click the button set this state to PAUSE and in your scene frame update loop test the state.
if (_state != PAUSE) {// Use enum for the state var
// Update scene objects
}
when your button is clicked:
Add pause label to scene
Set state to PAUSE
The benefits of this approach is that it allows you to decide exactly what will happen on pause (opposing to pausing the whole scene). You can animate a cool background while in pause or do anything you'd like as this is totally in your control

Resources