I have tried searching other answers and I cannot find one that applies to my scenario. I am writing a game in swift and want to create a stopwatch that determines how the long the player is playing. When the user touches down, the stopwatch will start and when a certain action happens, then the timer stops and resets. I'd like to use minutes, seconds, milliseconds (i.e. 00:00.00).
Currently, the time function kind of works. It doesn't start at 0, it starts at the current seconds in time (I know thats when I start it, but I don't know how to start it at 0). It also only updates when I touch the screen, I need it to count from 00:00.00 and update on its own until the cancel action is fired.
Thank you for your time.
Here is what I have so far:
class GameScene: SKScene {
var activeTimer = SKLabelNode()
//var bestTime = SKLabelNode()
var startTime = TimeInterval()
//var currentTime = TimeInterval()
//var countingTime = TimeInterval()
var updateTimerAction = SKAction()
override func didMove(to view: SKView) {
activeTimer = self.childNode(withName: "active_timer") as! SKLabelNode
//bestTime = self.childNode(withName: "best_time") as! SKLabelNode
startTime = TimeInterval(Calendar.current.component(.second, from:Date()))
updateTimerAction = SKAction.sequence([SKAction.run(updateTimer), SKAction.wait(forDuration: 1.0)])
}
func startGame() {
// Other code
startGameTimer()
}
func resetGame() {
// Other code
stopGameTimer()
}
func startGameTimer() {
run(SKAction.repeatForever(updateTimerAction), withKey: "timer")
}
func updateTimer() {
activeTimer.text = stringFromTimeInterval(interval: startTime) as String
}
func stringFromTimeInterval(interval: TimeInterval) -> NSString {
let ti = NSInteger(interval)
let ms = Int((interval.truncatingRemainder(dividingBy: 1)) * 1000)
let seconds = ti % 60
let minutes = (ti / 60) % 60
return NSString(format: "%0.2d:%0.2d.%0.2d",minutes,seconds,ms)
}
func stopGameTimer() {
removeAction(forKey: "timer")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
startGame()
for touch in touches {
// other code
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
// other code
}
}
override func update(_ currentTime: TimeInterval) {
updateTimer()
if <action> {
// stop timer and reset game
resetGame()
}
}
Instead of using a TimeInterval object, it might be better to use a Timer object which calls a function that increments the value of a label (or an internal variable) from 0 onwards accordingly after every 1 second(or can be made lesser). And for stopping the clock just call the Timer object's invalidate function.
Check the documentation for more info: https://developer.apple.com/documentation/foundation/timer
The following lines of code come from an actual macOS game that I submitted to Mac App Store some 3 weeks ago. It counts down a number to 0. In your case, change
self.currentSeconds -= 1
to
self.currentSeconds += 1
timeBackNode is an empty node that holds SKLabelNode objects timeNode0 and timeNode1. So create it when the game starts with didMove.
var currentSeconds = Int() // currentSeconds
var timeNode0 = SKLabelNode() // timeNode0
var timeNode1 = SKLabelNode() // timeNode1
func setupTimeGoal() {
enumerateChildNodes(withName: "//TimerBack", using: { timeBackNode, _ in
let goal = self.timeDict["num"] as! Int
self.currentSeconds = goal // In your case, goal is 0 since you are going to count up.
self.timeNode0 = SKLabelNode(fontNamed: "Your font's font name")
self.timeNode0.text = self.makeTimeWithSeconds(secs: goal)
self.timeNode0.fontSize = 26
self.timeNode0.fontColor = SKColor.black
self.timeNode0.horizontalAlignmentMode = .center
self.timeNode0.position = CGPoint(x: 1, y: -22)
timeBackNode.addChild(self.timeNode0)
self.timeNode1 = SKLabelNode(fontNamed: "Your font's font name")
self.timeNode1.text = self.makeTimeWithSeconds(secs: goal) // this function translate a counting number into a time code like 00:00:00
self.timeNode1.fontSize = 26
self.timeNode1.fontColor = SKColor.cyan
self.timeNode1.horizontalAlignmentMode = .center
self.timeNode1.position = CGPoint(x: 0, y: -23)
timeBackNode.addChild(self.timeNode1)
})
}
func repeatTime() {
let waitAction = SKAction.wait(forDuration: 1.0)
let completionAction = SKAction.run {
if self.currentSeconds == 0 && self.gameState == .playing {
self.removeAction(forKey: "RepeatTime")
self.proceedLoss()
return
}
self.currentSeconds -= 1
self.timeNode0.text = self.makeTimeWithSeconds(secs: self.currentSeconds)
self.timeNode1.text = self.makeTimeWithSeconds(secs: self.currentSeconds)
}
let seqAction = SKAction.sequence([waitAction, completionAction])
let repeatAction = SKAction.repeatForever(seqAction)
self.run(repeatAction, withKey: "RepeatTime")
}
Here is what I ended up doing. While El Tomato's answer appears to work, given the setup of my code I went a little different route. After talking with some other friends, I chose to user a timer due to the design of my application. If I happen to run into any problems using a Timer object I will update this question.
The code below will start on a touch, update in the format: "00:00.00" and stop when the action is fired. This time will pause until another touch and the timer will then start from zero.
class GameScene: SKScene {
var seconds = 0
var timer = Timer()
var timeStarted = Bool()
var activeTimer = SKLabelNode()
//var bestTime = SKLabelNode()
override func didMove(to view: SKView) {
activeTimer = self.childNode(withName: "active_timer") as! SKLabelNode
//bestTime = self.childNode(withName: "best_time") as! SKLabelNode
timeStarted = false
}
func startGame() {
startGameTimer()
timeStarted = true
}
func resetGame() {
timeStarted = false
stopGameTimer()
seconds = 0
}
func startGameTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
}
func updateTimer() {
seconds += 1
activeTimer.text = timeString(time: TimeInterval(seconds))
}
func timeString(time:TimeInterval) -> String {
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i.%02i", hours, minutes, seconds)
}
func stopGameTimer() {
timer.invalidate()
removeAction(forKey: "timer")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if !timeStarted {
startGame()
}
for touch in touches {
// other code
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
// other code
}
}
override func update(_ currentTime: TimeInterval) {
if timeStarted {
updateTimer()
}
if <action> {
// stop timer and reset game
resetGame()
}
}
}
Related
I am currently experimenting with some code that I found on the internet about a game where you have to click on one set of items and avoid clicking on the other. I am currently trying to add a timer to the game so that it lasts of a total of 30 seconds but I am really struggling to do so as I am quite inexperienced with this programming language.
import UIKit
import QuartzCore
import SceneKit
class GameViewController: UIViewController, SCNSceneRendererDelegate {
var gameView:SCNView!
var SceneGame:SCNScene!
var NodeCamera:SCNNode!
var targetCreationTime:TimeInterval = 0
override func viewDidLoad() {
super.viewDidLoad()
View_in()
initScene()
initCamera()
}
func View_in(){
gameView = self.view as! SCNView
gameView.allowsCameraControl = true
gameView.autoenablesDefaultLighting = true
gameView.delegate = self
}
func initScene (){
SceneGame = SCNScene()
gameView.scene = SceneGame
gameView.isPlaying = true
}
func initCamera(){
NodeCamera = SCNNode()
NodeCamera.camera = SCNCamera()
NodeCamera.position = SCNVector3(x:0, y:5, z:10)
SceneGame.rootNode.addChildNode(NodeCamera)
}
func createTarget(){
let geometry:SCNGeometry = SCNPyramid( width: 1, height: 1, length: 1)
let randomColor = arc4random_uniform(2
) == 0 ? UIColor.green : UIColor.red
geometry.materials.first?.diffuse.contents = randomColor
let geometryNode = SCNNode(geometry: geometry)
geometryNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
if randomColor == UIColor.red {
geometryNode.name = "enemy"
}else{
geometryNode.name = "friend"
}
SceneGame.rootNode.addChildNode(geometryNode)
let randomDirection:Float = arc4random_uniform(2) == 0 ? -1.0 : 1.0
let force = SCNVector3(x: randomDirection, y: 15, z: 0)
geometryNode.physicsBody?.applyForce(force, at: SCNVector3(x: 0.05, y: 0.05, z: 0.05), asImpulse: true)
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
if time > targetCreationTime{
createTarget()
targetCreationTime = time + 0.6
}
cleanUp()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in: gameView)
let hitList = gameView.hitTest(location, options: nil)
if let hitObject = hitList.first{
let node = hitObject.node
if node.name == "friend" {
node.removeFromParentNode()
self.gameView.backgroundColor = UIColor.black
}else {
node.removeFromParentNode()
self.gameView.backgroundColor = UIColor.red
}
}
}
func cleanUp() {
for node in SceneGame.rootNode.childNodes {
if node.presentation.position.y < -2 {
node.removeFromParentNode()
}
}
}
override var shouldAutorotate: Bool {
return true
}
override var prefersStatusBarHidden: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
}
You could use a Timer object, documented here. Just set up the timer when you want the game to start, probably once you've finished all your initializations. When you set up the timer, just wait for it to call back to your code when it finishes and run whatever logic you want to use to terminate your game.
EDIT
Create a variable representing the time you want your game will end:
var time: CGFloat = 60
Then, add an SCNAction to your scene so that each second it will decrease this variable value, for example in the viewDidLoad:
//One second before decrease the time
let wait = SCNAction.wait(forDuration: 1)
//This is the heart of this answer
// An action that reduce the time and when it is less than 1 (it reached zero) do whatever you want
let reduceTime = SCNAction.run{ _ in
self.time -= 1
if self.time < 1 {
// Do whatever you want
// for example show a game over scene or something else
}
}
}
SceneGame.rootNode.run(SCNAction.repeatForever(SCNAction.sequence([wait,reduceTime])))
If you want, you can show the remaining time by using SKLabel on an HUD, which is an SKScene used as overlay.
You can check this tutorial for how to create an HUD
As well, you can use an SCNText, this is the documentation about it
I am working on an arrow shooting game - The player need to shoot 3 arrows to a moving target (the target moves from left to right). When an arrow hits the target it should move with it (left to right). The most obvious thing to do would be to change the arrow parent to the target. From some reason its causing me some troubles -
I tried --- arrow.move(toParent:target) and I don't see the arrow on the screen even after I set a new location for it
If I simply --- target.addChild(arrow) I get a failure since I did not remove the arrow from its parent (which is the scene in this case)
When I --- arrow.removeFromParent() and then target.addChild(arrow) its causing other arrows to collide with each other and I still don't see the arrow on the screen.
This is my code -
class GameScene: SKScene, SKPhysicsContactDelegate {
var target:SKSpriteNode?
var arrows = [SKSpriteNode]()
var arrowContactPoint:CGPoint?
let noCategory:UInt32 = 0
let arrowCategory:UInt32 = 0b1
let targetCategory:UInt32 = 0b1 << 1
let obstacleCategory:UInt32 = 0b1 << 2
override func didMove(to view: SKView) {
allowCollisionDetection()
setTarget()
moveTargetFromSideToSide()
newArrow()
}
func didBegin(_ contact: SKPhysicsContact) {
let categoryBitMaskBodyA:UInt32 = contact.bodyA.categoryBitMask
let categoryBitMaskBodyB:UInt32 = contact.bodyB.categoryBitMask
if ((categoryBitMaskBodyA == targetCategory && categoryBitMaskBodyB == arrowCategory) || (categoryBitMaskBodyA == arrowCategory && categoryBitMaskBodyB == targetCategory)) {
arrowContactPoint = contact.contactPoint
arrowCollideWithTarget()
} else if (categoryBitMaskBodyA == obstacleCategory || categoryBitMaskBodyB == obstacleCategory) {
let obstacleNode:SKNode = ((categoryBitMaskBodyA == arrowCategory) ? contact.bodyA.node! : contact.bodyB.node)!
arrowCollideWithObstacle(obstacle:obstacleNode)
} else if (categoryBitMaskBodyA == arrowCategory && categoryBitMaskBodyB == arrowCategory) {
newGame()
} else {
print("Something went wrong")
}
newArrow()
}
func touchDown(atPoint pos : CGPoint) {
}
func touchMoved(toPoint pos : CGPoint) {
}
func touchUp(atPoint pos : CGPoint) {
shootArrow()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
func allowCollisionDetection() {
self.physicsWorld.contactDelegate = self
}
func setTarget() {
target = self.childNode(withName: "target") as? SKSpriteNode
//Set the target bit mask, it's tag
target?.physicsBody?.categoryBitMask = targetCategory
//Set with which objects the target collide
target?.physicsBody?.collisionBitMask = noCategory
//Set to which coliision we want to responde/handle - didBegin will get triggered
target?.physicsBody?.contactTestBitMask = arrowCategory
}
func moveTargetFromSideToSide() {
let moveRight = SKAction.moveBy(x: frame.size.width - (target?.size.width)!, y: 0, duration: 2)
let moveLeft = SKAction.moveBy(x: -(frame.size.width - (target?.size.width)!), y: 0, duration: 2)
let moveBackAndForth = SKAction.repeatForever(SKAction.sequence([moveRight, moveLeft]))
target?.run(moveBackAndForth)
}
func newArrow() {
let arrow = SKSpriteNode(imageNamed: "arrow1")
let arrowTexture = SKTexture(imageNamed: "arrow1")
arrow.position = CGPoint.zero
self.addChild(arrow)
arrow.physicsBody = SKPhysicsBody(texture: arrowTexture, size: arrowTexture.size())
arrow.physicsBody?.isDynamic = true
arrow.physicsBody?.allowsRotation = true
arrow.physicsBody?.affectedByGravity = false
arrow.physicsBody?.friction = 0.2
arrow.physicsBody?.restitution = 0.2
arrow.physicsBody?.linearDamping = 0.1
arrow.physicsBody?.angularDamping = 0.1
arrow.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
arrow.physicsBody?.categoryBitMask = arrowCategory
arrow.physicsBody?.collisionBitMask = noCategory
arrow.physicsBody?.contactTestBitMask = arrowCategory | obstacleCategory | targetCategory
arrows.append(arrow)
}
func shootArrow(){
print("shootArrow")
arrows.last!.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 80))
}
func arrowCollideWithTarget() {
print("arrowCollideWithTarget")
arrows.last!.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
arrows.last!.move(toParent: target!)
}
func arrowCollideWithObstacle(obstacle:SKNode) {
print("arrowCollideWithObstacle")
arrows.last!.removeFromParent()
arrows.removeLast()
}
func newGame() {
print("New Game")
for i in 0 ..< (arrows.count) {
arrows[i].removeFromParent()
}
arrows.removeAll()
}
}
What eventually solved it for me was using this method ---
move(toParent: )
This is my code -
func arrowCollideWithTarget() {
arrows.last!.move(toParent:target!)
}
The code works fine when the window is open in the foreground and when I press the space key, the mouse moves as expected, but as soon as I move to another application and I press the space key, the mouse no longer moves as expected with the keystroke, How do I keep the application working even when it is set to the background
import Cocoa
class ViewController: NSViewController {
var timer: Timer!
#objc func movethemouse() {
let mouseLocx = NSEvent.mouseLocation.x
let mouseLocy = NSEvent.mouseLocation.y
let screenH = NSScreen.main?.frame.height
let deltaX = CGFloat(Int(1))
let deltaY = CGFloat(Int(1))
let newLoc = CGPoint(x: mouseLocx + deltaX , y: screenH! - mouseLocy - deltaY )
CGDisplayMoveCursorToPoint(CGMainDisplayID(), newLoc)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear() {
view.window?.makeFirstResponder(self)
}
override var acceptsFirstResponder : Bool {
return true
}
var count3=0
var flag = false
override func keyDown(with event: NSEvent) {
if (event.keyCode == 49){
flag = true
if count3 == 0 {
timer = Timer.scheduledTimer(timeInterval: 0.001, target:self, selector: #selector(ViewController.movethemouse), userInfo: nil, repeats:true)
print(event)
}
count3 += 1
}
}
override func keyUp(with event: NSEvent) {
print(event)
if (event.keyCode == 49) {
if flag {
timer.invalidate()
count3 = 0
print(event)
}
}
}
}
You need to capture system wide events. Here's some sample code that will get everything in the system. Note that you have to enable assistive mode for XCode (during development) or your app (running outside XCode) for this to work.
func applicationDidFinishLaunching(_ aNotification: Notification) {
if getAccessibility() {
snarfKeys()
}
// etc...
}
func getAccessibility() -> Bool {
let trusted = AXIsProcessTrusted()
if !trusted {
print("process is not trusted")
}
return trusted
}
func snarfKeys() {
NSEvent.addGlobalMonitorForEvents(matching: .keyUp, handler: keyPress)
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseUp, handler: mousePress)
}
snarfKeys does the magic, but as noted above and in the code, the process needs to be trusted to be able to add global event monitoring.
I'm working on simple game which will based on paiting background by player. In left and right corner there will be buttons which will move character to left or right. I've already implemented that (character is moving and lefts painted background behind), but with adding another circles fps's drops really fast. Is there any solution to that?
import SpriteKit
class GameScene: SKScene {
var playerDot:PlayerDot = PlayerDot(imageNamed:"player")
var isTurningLeft:Bool = false
var isTurningRight:Bool = false
var lastLocation:CGPoint = CGPoint()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let myLabel = SKLabelNode(fontNamed:"Helvetica")
myLabel.name = "left"
myLabel.text = "Left"
myLabel.fontSize = 30
myLabel.horizontalAlignmentMode = .Left
myLabel.position = CGPoint(x:CGRectGetMinX(self.frame), y:CGRectGetMinY(self.frame))
self.addChild(myLabel)
let myLabel2 = SKLabelNode(fontNamed:"Helvetica")
myLabel2.name = "right"
myLabel2.text = "Right"
myLabel2.fontSize = 30
myLabel2.horizontalAlignmentMode = .Right
myLabel2.position = CGPoint(x:CGRectGetMaxX(self.frame), y:CGRectGetMinY(self.frame))
self.addChild(myLabel2)
playerDot.position = CGPoint(x:CGRectGetMaxX(self.frame)/2, y:CGRectGetMinY(self.frame))
self.addChild(playerDot)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if let theName = self.nodeAtPoint(location).name {
if theName == "left" {
isTurningLeft = true
isTurningRight = false
}
else if theName == "right" {
isTurningRight = true
isTurningLeft = false
}
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if let theName = self.nodeAtPoint(location).name {
if theName == "left" {
isTurningLeft = false
}
else if theName == "right" {
isTurningRight = false
}
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if let theName = self.nodeAtPoint(location).name {
if theName == "left" {
isTurningLeft = false
}
else if theName == "right" {
isTurningRight = false
}
}
}
}
override func update(currentTime: CFTimeInterval) {
if(isTurningLeft){
playerDot.increaseAngle()
} else if (isTurningRight){
playerDot.decreaseAngle()
}
//calculates new character position based on angle of movement changed
playerDot.updatePosition()
drawCircle()
}
func drawCircle(){
if(distanceFromCGPoints(lastLocation, b: playerDot.position)>2){
let circle = SKShapeNode(circleOfRadius: 10 )
circle.position = playerDot.position
circle.fillColor = SKColor.orangeColor()
circle.strokeColor = SKColor.orangeColor()
self.addChild(circle)
lastLocation = playerDot.position
}
}
func distanceFromCGPoints(a:CGPoint,b:CGPoint)->CGFloat{
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
func random() -> CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}
}
EDIT:
drawCircle with SKShapeNode replaced with SKSpriteNote
func drawCircle(){
if(distanceFromCGPoints(lastLocation, b: playerDot.position)>2){
let playerDot2 = SKSpriteNode(imageNamed:"player")
playerDot2.position = playerDot.position
self.addChild(playerDot2)
lastLocation = playerDot.position
}
}
If you are having frame rate drops then some parts of your code are slowing down execution too much. You need to optimise your code. Use Instruments (Time Profiler) to find out which lines/functions are causing problems speed wise. If you have never used it before read up on it and use it a couple times to get the gist, then I recommend watching the WWDC video Profiling In-Depth
Based on your edit (switching to SKSpriteNode), this is how you could do it:
Declare a texture as a property of your scene. This way, you load it once and reuse it later:
let yourTexture = SKTextureAtlas(named: "yourAtlas").textureNamed("yourTexture")
Then in your drawCircle method:
func drawCircle(){
if(distanceFromCGPoints(lastLocation, b: playerDot.position)>2){
let playerDot2 = SKSpriteNode(texture: yourTexture)
playerDot2.position = playerDot.position
self.addChild(playerDot2)
lastLocation = playerDot.position
}
}
This way (by using SKSpriteNode instead of SKShapeNode) you have reduced number of draw calls required to render all those circles. Also because you are reusing the same texture, instead of allocating it every time using imageNamed you have reduced greatly an amount of memory that app consumes. Now, SpriteKit can render hundreds of nodes #60 fps if those nodes are rendered in batches. Still there is a limit before fps start dropping. And that depends on a device.
I was testing my game on my iPhone and I realized that I have a problem with the home button. When I pause the game and load another app the game is not paused and continues when the app is not on screen.
Here's the code:
class GameScene: SKScene, SKPhysicsContactDelegate{
var PauseButton = SKSpriteNode(imageNamed: "pause")
var Resume = SKSpriteNode(imageNamed: "resume1")
}
init(size: CGSize, won: Bool) {
super.init(size: size)
//pause
PauseButton.position = CGPointMake(330, 700)
PauseButton.zPosition = 3;
PauseButton.size = CGSizeMake(40, 40);
PauseButton.name = "PauseButton"
self.addChild(PauseButton)
//resume
Resume = SKSpriteNode(imageNamed: "resume1")
Resume.position = CGPointMake(520, 450)
Resume.zPosition = 100
Resume.setScale(1.3)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
show = self.scene as SKScene!
for touch in touches {
let Location:CGPoint = touch.locationInNode(self)
let Node:SKNode = self.nodeAtPoint(Location)
if(Node == PauseButton){
self.show.paused = true
PauseButton.removeFromParent()
self.addChild(Resume)
}
if(Node == Resume){
Resume.removeFromParent()
self.show.paused = false
self.addChild(PauseButton)
}
How do I get the game to pause when I press the home button?
Pause the view not the scene.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let view = view else {
return
}
view.paused = !view.paused
}
SpriteKit will auto Resume when you comeback to your app. so you need :
Step 1 : create a variable :
var wasPaused : Bool = false
Step 2 : change it in your pause/resume function :
wasPaused = true // pause func
wasPaused = false // resume fun
Step 3 : in update fun of your scene:
override func update(currentTime: CFTimeInterval) {
if isPausing{
self.paused = true
return
}
}