Sprite Moves Two Places After Being Paused and Then Unpaused

Sprite moves two places after being paused and then unpaused

As the member above me said the player is not really moving 2 spaces.

Also you should maybe change your strategy when pausing your game, because pausing the scene.view makes it very hard to add SpriteKit elements afterwards.

I think a better way is to create a worldNode in your GameScene and add all the sprites that need to be paused to that worldNode. It basically gives you more flexibility pausing a node rather than the whole scene.

First create a world node property

 let worldNode = SKNode()

and add it to the scene in ViewDidLoad

 addChild(worldNode)

Than add all the sprites you need paused to the worldNode

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

Create a global enum for your game states

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

Than make a pause and resume func in your game scene

func pause() {
GameState.current = .Paused

// show pause menu etc
}

func resume() {
GameState.current = .Playing
self.physicsWorld.speed = 1
worldNode.paused = false
}

And finally add the actual pause code to your updateMethod. This way it will not resume the game even if spriteKit itself tries to resume (e.g. reopened app, dismissed alert etc)

 override func update(currentTime: CFTimeInterval) {

if GameState.current == .Paused {
self.physicsWorld.speed = 0
worldNode.paused = true
}
}

In regards to your tapGesture recogniser, in the method that gets called after a tap you can add this before the rest of the code

 guard GameState.current != .Paused else { return }
....

Hope this helps

How to prevent run SKAction on paused scene (after unpaused), texture of node not change after pause/unpause scene

I put my controls on their own layer (SKNode) controlsLayer.addChild(pauseButton) and game objects on their own layer "gameLayer" then when I want to pause the game, I just pause the gameLayer (gameLayer.isPaused = true). This stops the game objects from moving, gives the appearance of being paused but still allows me to things like actions, add objects etc.

override func update(_ currentTime: TimeInterval) {

if !gameLayer.isPaused {
moveBackground()
}
}

Paused layer come unpause after start app from background

So this is what worked for me:

import SpriteKit
import GameplayKit

class GameScene: SKScene {

var gameLayer = SKNode()

override func didMove(to view: SKView) {
NotificationCenter.default.addObserver(self,
selector: #selector(GameScene.pause),
name: .UIApplicationDidBecomeActive,
object: nil)
let moveUp = SKAction.moveBy(x: 0, y: 100, duration: 2)
let sequence = SKAction.sequence([moveUp, moveUp.reversed()])
let loop = SKAction.repeatForever(sequence)

let sprite = SKSpriteNode(color: .purple, size: CGSize(width: 100, height: 100))

addChild(gameLayer)
gameLayer.addChild(sprite)

sprite.run(loop)
}

func pause(){

gameLayer.speed = 0
}

override func willMove(from view: SKView) {
super.willMove(from: view)

NotificationCenter.default.removeObserver(self,
name: .UIApplicationDidBecomeActive,
object: nil)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

gameLayer.speed = gameLayer.speed == 0 ? 1 : 0
}
}

I haven't had time to test more, but I was expecting that something like this:

 func pause(){
gameLayer.isPaused = true
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
gameLayer.isPaused = !gameLayer.isPaused
}

would work, but surprisingly it isn't (the node continued with moving after the pause() method was executed). I don't really know if this is a bug or a feature :) but IMHO, I would say it is a bug. Anyways, you can achieve what you want using the speed property. Just copy and paste this code to see how it works.

cancelling a tap gesture recongiser

You can remove Gesture on Pause click using following:

self.view.removeGestureRecognizer(YOUR_GESTURE_RECOGNISER)

and add it again if resume game

iOS unpausing game after didBecomeActive

Now I have your source, I see your problem.

You need to preserve your pause state:

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

}

}
}

For some reason, scene paused is deciding to unpause all nodes under it

Also, you should pause your game when you leave the app, not when you come back.

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

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

And you can get rid of that check paused variable, that is redundant bloat code.

Keeping the game paused after app become active?

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.

GameplayKit Not Pausing When Scene Is Paused

Agents will continue along their last known valid velocity if another goal isn't altering it. If you'd like the agents to stop you could try using GKGoal's goalToReachTargetSpeed:.



Related Topics



Leave a reply



Submit