Accelerometer works in first game, but goes crazy in the second - ios

I'm creating a game where a player will control a falling sprite with the accelerometer X axis and an impulse is added when the user taps on the screen. In my current code when I run the game, it works okay and then once the player dies and tries again the sprite goes crazy and just flies of the screen. Can someone help please...
class PlayScene: SKScene, SKPhysicsContactDelegate {
var score = 0
var scoreLabel = SKLabelNode()
var gameOverLabel = SKLabelNode()
var labelHolder = SKSpriteNode()
var background = SKSpriteNode()
let playerGroup:UInt32 = 1
let objectGroup:UInt32 = 2
let gapGroup:UInt32 = 0 << 3
let boundary:UInt32 = 4
var movingObjects = SKNode()
var motionManager = CMMotionManager()
var destX:CGFloat = 0.0
var gameOver = 0
var currentX: CGFloat?
let greenPlayer = SKSpriteNode(imageNamed: "Image/Players/greenPlayer.png")
override func didMoveToView(view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsWorld.contactDelegate = self
self.physicsBody!.friction = 0
self.physicsWorld.gravity = CGVectorMake(-0.0, -0.8)
self.addChild(labelHolder)
scoreLabel.fontName = "Helvetica"
scoreLabel.fontSize = 60
scoreLabel.text = "0"
scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height - 140)
scoreLabel.zPosition = 10
self.addChild(scoreLabel)
//self.physicsWorld.contactDelegate = self
self.addChild(movingObjects)
let backgroundTexture = SKTexture(imageNamed: "Image/TempBG.png")
background=SKSpriteNode(texture: backgroundTexture)
background.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
background.size.width = self.frame.width
background.zPosition = 0
self.addChild(background)
greenPlayer.physicsBody = SKPhysicsBody(circleOfRadius: greenPlayer.size.height/2)
greenPlayer.physicsBody?.dynamic = true
greenPlayer.physicsBody?.allowsRotation = false
greenPlayer.physicsBody?.categoryBitMask = playerGroup
greenPlayer.physicsBody?.collisionBitMask = objectGroup
greenPlayer.physicsBody?.contactTestBitMask = objectGroup
greenPlayer.physicsBody?.collisionBitMask = gapGroup
greenPlayer.physicsBody?.collisionBitMask = boundary
//self.greenPlayer.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.greenPlayer.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
greenPlayer.zPosition = 5
self.addChild(greenPlayer)
currentX = self.greenPlayer.position.x
//if motionManager.accelerometerAvailable == true {
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue()!, withHandler:{ data, error in
if data!.acceleration.x < 0 {
self.destX = self.currentX! + CGFloat(data!.acceleration.x * 1000)
}
else if data!.acceleration.x > 0 {
self.destX = self.currentX! + CGFloat(data!.acceleration.x * 1000)
}
})
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: Selector("makeDodges"), userInfo: nil, repeats: true)
}
func makeDodges() {
if(gameOver == 0){
let gapWidth = greenPlayer.size.width * 3
let movementAmount = arc4random() % UInt32(self.frame.size.width / 2)
let dodgeOffSet = CGFloat(movementAmount) - (self.frame.size.width / 4)
let moveDodges = SKAction.moveByX(0, y: self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
let removeDodges = SKAction.removeFromParent()
let moveAndRemoveDodges = SKAction.sequence([moveDodges, removeDodges])
let dodge1Texture = SKTexture(imageNamed: "Image/Dodge.png")
let dodge1 = SKSpriteNode(texture: dodge1Texture)
dodge1.position = CGPoint(x: CGRectGetMidX(self.frame) + dodge1.size.width/2 + gapWidth/2 + dodgeOffSet, y: CGRectGetMidY(self.frame) - self.frame.size.height)
dodge1.runAction(moveDodges)
dodge1.physicsBody = SKPhysicsBody(rectangleOfSize: dodge1.size)
dodge1.physicsBody?.dynamic = false
dodge1.physicsBody?.categoryBitMask = objectGroup
dodge1.zPosition = 10
movingObjects.addChild(dodge1)
let dodge2Texture = SKTexture(imageNamed: "Image/Dodge.png")
let dodge2 = SKSpriteNode(texture: dodge2Texture)
dodge2.position = CGPoint(x: CGRectGetMidX(self.frame) - dodge2.size.width/2 - gapWidth/2 + dodgeOffSet , y: CGRectGetMidY(self.frame) - self.frame.size.height)
dodge2.runAction(moveDodges)
dodge2.physicsBody = SKPhysicsBody(rectangleOfSize: dodge2.size)
dodge2.physicsBody?.dynamic = false
dodge2.physicsBody?.categoryBitMask = objectGroup
dodge2.zPosition = 10
movingObjects.addChild(dodge2)
let gap = SKNode()
gap.position = CGPoint(x: CGRectGetMidX(self.frame) + dodgeOffSet , y: CGRectGetMidY(self.frame) - self.frame.size.height)
gap.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(dodge1.size.height, gapWidth))
gap.runAction(moveAndRemoveDodges)
gap.physicsBody?.dynamic = false
gap.physicsBody?.collisionBitMask = gapGroup
gap.physicsBody?.categoryBitMask = gapGroup
gap.physicsBody?.contactTestBitMask = playerGroup
movingObjects.addChild(gap)
}
}
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == gapGroup || contact.bodyB.categoryBitMask == gapGroup {
score++
print(score)
scoreLabel.text = "\(score)"
} else {
if gameOver == 0 {
gameOver = 1
movingObjects.speed = 0
let scene:SKScene = GameScene(size: self.frame.size)
scene.scaleMode = .AspectFill
let transition:SKTransition = SKTransition.fadeWithDuration(2)
self.view?.presentScene(scene, transition: transition)
}
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if(gameOver == 0) {
greenPlayer.physicsBody?.velocity = CGVectorMake(0, 0)
greenPlayer.physicsBody?.applyImpulse(CGVectorMake(0, 50))
} else {
score = 0
scoreLabel.text = "0"
movingObjects.removeAllChildren()
self.greenPlayer.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
greenPlayer.physicsBody?.velocity = CGVectorMake(0, 0)
labelHolder.removeAllChildren()
gameOver = 0
movingObjects.speed = 1
currentX = CGRectGetMidX(self.frame)
}
}
override func update(currentTime: CFTimeInterval) {
let action = SKAction.moveToX(destX, duration: 1)
self.greenPlayer.runAction(action)
}
}

You never stop and remove the old motion manager queue, so your old scene will never die, thus causing your problems.
Add motionManager.stopAccelerometerUpdates();motionManager = nil; at the point you want to destroy your old scene, If you are not destroying your old scene, and just resetting your data, then just add motionManager.stopAccelerometerUpdates(); to the point where you are going to reset your scene.

Related

share menu opens at twice rather just when button is pressed

I have added a share menu to my game, when the game is over the game over pop up appears with a share menu. when i press anywhere on the screen the share menu pops up and the game goes back to the beginning prompting the player to Tap to play again. Then when the player taps on the screen the share menu pops up again which makes the game unplayable after the first play through. I think i need to set the share menu to pop up only when SKSpriteNode for the share button is pressed, if the player taps anywhere else on the screen the game should just reset. Would be grateful if you could take a look at code and see where i am going wrong.
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var shareButton = SKSpriteNode()
var santa = SKSpriteNode()
var bg = SKSpriteNode()
var scoreLabel = SKLabelNode()
var tapToPlayLabel = SKLabelNode()
var score = 0
var gameOverScreen = SKSpriteNode()
var timer = Timer()
enum ColliderType: UInt32 {
case santa = 1
case Object = 2
case Gap = 4
}
enum ButtonName: String {
case play
case share
}
var gameOver = false
func makeBlocks() {
let moveBlocks = SKAction.move(by: CGVector(dx: -2 * self.frame.width, dy: 0), duration: TimeInterval(self.frame.width / 100))
let gapHeight = santa.size.height * 4
let movementAmount = arc4random() % UInt32(self.frame.height / 2)
let blockOffset = CGFloat(movementAmount) - self.frame.height / 4
let blockTexture = SKTexture(imageNamed: "block1.png")
let block1 = SKSpriteNode(texture: blockTexture)
block1.position = CGPoint(x: self.frame.midX + self.frame.width, y: self.frame.midY + blockTexture.size().height / 2 + gapHeight / 2 + blockOffset)
block1.run(moveBlocks)
block1.physicsBody = SKPhysicsBody(rectangleOf: blockTexture.size())
block1.physicsBody!.isDynamic = false
block1.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
block1.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
block1.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
block1.zPosition = -2
self.addChild(block1)
let block2Texture = SKTexture(imageNamed: "block2.png")
let block2 = SKSpriteNode(texture: block2Texture)
block2.position = CGPoint(x: self.frame.midX + self.frame.width, y: self.frame.midY - block2Texture.size().height / 2 - gapHeight / 2 + blockOffset)
block2.run(moveBlocks)
block2.physicsBody = SKPhysicsBody(rectangleOf: blockTexture.size())
block2.physicsBody!.isDynamic = false
block2.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
block2.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
block2.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
block2.zPosition = -2
self.addChild(block2)
let gap = SKNode()
gap.position = CGPoint(x: self.frame.midX + self.frame.width, y: self.frame.midY + blockOffset)
gap.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: blockTexture.size().width, height: gapHeight))
gap.physicsBody!.isDynamic = false
gap.run(moveBlocks)
gap.physicsBody!.contactTestBitMask = ColliderType.santa.rawValue
gap.physicsBody!.categoryBitMask = ColliderType.Gap.rawValue
gap.physicsBody!.collisionBitMask = ColliderType.Gap.rawValue
self.addChild(gap)
}
func didBegin(_ contact: SKPhysicsContact) {
if gameOver == false {
if contact.bodyA.categoryBitMask == ColliderType.Gap.rawValue || contact.bodyB.categoryBitMask == ColliderType.Gap.rawValue {
score += 1
scoreLabel.text = String(score)
} else {
self.speed = 0
gameOver = true
timer.invalidate()
let gameOverScreenTexture = SKTexture(imageNamed: "GameOverPopup.jpg")
var j: CGFloat = 0
gameOverScreen = SKSpriteNode(texture: gameOverScreenTexture, size: CGSize(width: 600, height: 600))
gameOverScreen.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
gameOverScreen.size.height = self.frame.height / 3
gameOverScreen.zPosition = -1
self.addChild(gameOverScreen)
//share button
let shareButtonTexture = SKTexture(imageNamed: "shareButton.png")
var k: CGFloat = 0
shareButton = SKSpriteNode(texture: shareButtonTexture, size: CGSize(width: 500, height: 100))
shareButton.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
shareButton.size.height = self.frame.height / 10
shareButton.name = "shareButton"
shareButton.zPosition = 0
self.addChild(shareButton)
}
}
}
func openShareMenu(value: String, image: UIImage?) {
guard let view = view else { return }
// Activity items
var activityItems = [AnyObject]()
// Text
let text = "Can you beat my score "
activityItems.append(text as AnyObject)
// Add image if valid
if let image = image {
activityItems.append(image)
}
// Activity controller
let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
// Excluded activity types
activityController.excludedActivityTypes = [
UIActivityType.airDrop,
UIActivityType.print,
UIActivityType.assignToContact,
UIActivityType.addToReadingList,
]
// Present
view.window?.rootViewController?.present(activityController, animated: true)
}
override func didMove(to view: SKView) {
addChild(shareButton)
self.physicsWorld.contactDelegate = self
setupGame()
}
func setupGame() {
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.makeBlocks), userInfo: nil, repeats: true)
let bgTexture = SKTexture(imageNamed: "bg.png")
let moveBGAnimation = SKAction.move(by: CGVector(dx: -bgTexture.size().width, dy: 0), duration: 7)
let shiftBGAnimation = SKAction.move(by: CGVector(dx: bgTexture.size().width, dy: 0), duration: 0)
let moveBGForever = SKAction.repeatForever(SKAction.sequence([moveBGAnimation, shiftBGAnimation]))
var i: CGFloat = 0
while i < 3 {
bg = SKSpriteNode(texture: bgTexture)
bg.position = CGPoint(x: bgTexture.size().width * i, y: self.frame.midY)
bg.size.height = self.frame.height
bg.run(moveBGForever)
bg.zPosition = -3
self.addChild(bg)
i += 1
}
let santaTexture = SKTexture(imageNamed: "santa1.png")
let santaTexture2 = SKTexture(imageNamed: "santa2.png")
let animation = SKAction.animate(with: [santaTexture, santaTexture2], timePerFrame: 0.1)
let makeSantaMove = SKAction.repeatForever(animation)
santa = SKSpriteNode(texture: santaTexture)
santa.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
santa.run(makeSantaMove)
santa.physicsBody = SKPhysicsBody(circleOfRadius: santaTexture.size().height / 2)
santa.physicsBody!.isDynamic = false
santa.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
santa.physicsBody!.categoryBitMask = ColliderType.santa.rawValue
santa.physicsBody!.collisionBitMask = ColliderType.santa.rawValue
self.addChild(santa)
let ground = SKNode()
ground.position = CGPoint(x: self.frame.midX, y: -self.frame.height / 2)
ground.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.frame.width, height: 1))
ground.physicsBody!.isDynamic = false
ground.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
ground.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
ground.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
self.addChild(ground)
scoreLabel.fontName = "Helvetica"
scoreLabel.fontSize = 60
scoreLabel.text = "0"
scoreLabel.position = CGPoint(x: self.frame.midX, y: self.frame.height / 2 - 220)
self.addChild(scoreLabel)
tapToPlayLabel.fontName = "Helvetica"
tapToPlayLabel.fontSize = 70
tapToPlayLabel.text = "Tap to Play!"
tapToPlayLabel.position = CGPoint(x: self.frame.midX, y: self.frame.height / 2 - 500)
self.addChild(tapToPlayLabel)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if gameOver == false {
tapToPlayLabel.isHidden = true
santa.physicsBody!.isDynamic = true
santa.physicsBody!.velocity = CGVector(dx: 0, dy: 0)
santa.physicsBody!.applyImpulse(CGVector(dx: 0, dy: 320))
} else {
tapToPlayLabel.isHidden = false
gameOver = false
score = 0
self.speed = 1
self.removeAllChildren()
setupGame()
}
if let name = shareButton.name {
if name == "shareButton" {
openShareMenu(value: "\(self.score)", image: nil)
}
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
You are calling the touches method wrong. You are not using the name of the touched node to see if it is the share button. You merely assign a property (if let name = ...) and see if its the share button. You need to compare with the name of the actual node that is touched. You are also running your gameOver code anytime touchesBegan fires, you need to differentiate.
Try this
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self) // get location of touch
let nodeTouched = atPoint(location) // get touched node
// Pressed button
if let nodeName = nodeTouched.name {
switch nodeName {
case ButtonName.share.rawValue:
openShareMenu(value: "\(self.score)", image: nil)
return // return early if share button is pressed so your gameOver code below etc doesnt fire.
default:
break
}
}
// Did not press button, usual code
if gameOver == false {..... }
}
}
Hope this helps

Struggling with collision detection in Swift/SpriteKit

I'm having a play with game programming in Swift/Xcode and am struggling getting collision to work.
I'm using Xcode 8 Beta 3 (because I couldn't use Xcode 7 on MacOS Sierra) so its using the new Swift 3.0 Syntax. The game has a little puppy (defined in a SK Scene file) that jumps and collects thrown items from the right. The thrown item is created in a function and removed when a new item is thrown.
I need contact with the thrown item comes into contact with the puppy. I've got physics turned on and the item bounces off the puppy but no contact is registered.
Heres my code. Appologies for the mess of code but its very first attempt at Swift and everything just thrown in for now. I can't see what I'm doing wrong :(
UPDATE: As cocoajoe suggested, I've tried setting the masks to 1 and have simplified the code to remove references to the gamescene.sks file and created everything programmatically but its still not working. I've updated the code below to reflect the latest version of the code...
import SpriteKit
import AVFoundation
class GameScene: SKScene, SKPhysicsContactDelegate {
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder) is not used in this app")
}
override init(size: CGSize) {
super.init(size: size)
anchorPoint = CGPoint(x: 0.0, y: 0.0)
}
var isJumping = false
var gamePaused = false
var gameRunning = false
var playerScore = 0
var lastSpawnTime = 0
var lastTick = 0
var spawnDelay = 4
let PuppyCategory : UInt32 = 0x1 << 0
let ThrowableCategory : UInt32 = 0x1 << 1
let GroundCategory : UInt32 = 0x1 << 2
override func didMove(to view: SKView) {
physicsWorld.gravity = CGVector(dx: 0.0, dy: -9.8)
physicsWorld.contactDelegate = self
let background = SKSpriteNode(imageNamed: "bg")
background.anchorPoint = CGPoint(x: 0.0, y:0.0)
background.size = size
addChild(background)
// Set up Ground Object
let Ground = SKSpriteNode()
Ground.name = "Ground"
Ground.size = CGSize(width:frame.width, height: frame.height / 10)
Ground.position = CGPoint(x: frame.midX, y: Ground.frame.height / 2 )
Ground.zPosition = -20
Ground.color = SKColor.white()
// Set up the Physics
Ground.physicsBody = SKPhysicsBody(rectangleOf: Ground.size)
Ground.physicsBody!.categoryBitMask = GroundCategory
Ground.physicsBody!.contactTestBitMask = PuppyCategory | ThrowableCategory
Ground.physicsBody!.collisionBitMask = PuppyCategory | ThrowableCategory
Ground.physicsBody?.affectedByGravity = false
Ground.physicsBody?.allowsRotation = false
Ground.physicsBody?.isDynamic = false
Ground.physicsBody?.mass = 1.99999
// Initialise the Node
addChild(Ground)
// Create a Puppy
let Puppy = SKSpriteNode(imageNamed: "puppy1")
Puppy.name = "Puppy"
Puppy.position = CGPoint(x: frame.width / 10, y: frame.height / 2)
Puppy.size = CGSize(width: frame.width / 7, height: frame.height / 5)
Puppy.zPosition = 3
// Set up the Physics
Puppy.physicsBody = SKPhysicsBody(rectangleOf: Puppy.size)
Puppy.physicsBody!.categoryBitMask = PuppyCategory
Puppy.physicsBody!.contactTestBitMask = ThrowableCategory | GroundCategory
Puppy.physicsBody!.collisionBitMask = ThrowableCategory | GroundCategory
Puppy.physicsBody?.affectedByGravity = true
Puppy.physicsBody?.allowsRotation = false
Puppy.physicsBody?.isDynamic = true
Puppy.physicsBody?.mass = 1.99999
// Set up the Textures/Animation Frames
var TextureAtlas = SKTextureAtlas()
var TextureArray = [SKTexture]()
TextureAtlas = SKTextureAtlas(named: "puppy")
for i in 1...TextureAtlas.textureNames.count {
let Name = "puppy\(i).png"
TextureArray.append(SKTexture(imageNamed: Name))
}
Puppy.run(SKAction.repeatForever(SKAction.animate(with:TextureArray, timePerFrame: 0.1)))
// Add the Sprite
addChild(Puppy)
let gameMessage = SKSpriteNode(imageNamed: "TapToPlay")
gameMessage.name = "GameMessage"
gameMessage.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
gameMessage.zPosition = 30
gameMessage.setScale(0.0)
addChild(gameMessage)
let gameLogo = SKSpriteNode(imageNamed: "pjlogo")
gameLogo.name = "GameLogo"
gameLogo.size = CGSize(width: frame.width / 3, height: frame.height / 5)
gameLogo.position = CGPoint(x: frame.midX, y: (frame.maxY / 100) * 80)
gameLogo.zPosition = 30
addChild(gameLogo)
let scale = SKAction.scale(to: 1.0, duration: 1)
scene?.childNode(withName: "GameMessage")!.run(scale)
if let musicURL = Bundle.main.urlForResource("bgmusic", withExtension: "mp3") {
var backgroundMusic: SKAudioNode!
backgroundMusic = SKAudioNode(url: musicURL)
addChild(backgroundMusic)
}
startNewGame()
}
func puppyJump() {
if gameRunning {
let Puppy = childNode(withName: "Puppy")
if !isJumping {
Puppy?.physicsBody?.applyImpulse(CGVector(dx: 0,dy: 1400))
isJumping = true
}
}
}
func generateThrowable() {
print("new enemy")
let oldItem = childNode(withName: "throwableItem")
oldItem?.removeFromParent()
let throwableItem = SKSpriteNode(imageNamed: "puppy1")
throwableItem.name = "throwableItem"
throwableItem.position = CGPoint(x: frame.maxX, y: frame.midY)
throwableItem.zPosition = 3
throwableItem.setScale(0.1)
throwableItem.physicsBody = SKPhysicsBody(rectangleOf: throwableItem.size)
throwableItem.physicsBody!.categoryBitMask = ThrowableCategory
throwableItem.physicsBody!.contactTestBitMask = PuppyCategory | GroundCategory
throwableItem.physicsBody!.collisionBitMask = PuppyCategory | GroundCategory
throwableItem.physicsBody?.friction = 0.1
throwableItem.physicsBody?.restitution = 0.1
throwableItem.physicsBody?.mass = 0.01
throwableItem.physicsBody?.affectedByGravity = true
throwableItem.physicsBody?.allowsRotation = true
throwableItem.physicsBody?.isDynamic = true
addChild(throwableItem)
throwableItem.physicsBody?.applyImpulse(CGVector(dx: -7,dy: 4))
let throwableTrail = SKEmitterNode(fileNamed: "particleTrail.sks")
throwableTrail?.name = "throwableTrail"
throwableTrail?.targetNode = scene
throwableItem.addChild(throwableTrail!)
}
func startNewGame() {
let logo = childNode(withName: "GameLogo")
let gameMessage = childNode(withName: "GameMessage")
logo?.removeFromParent()
gameMessage?.removeFromParent()
let gameScore = SKLabelNode(fontNamed: "Arial")
gameScore.name = "GameScore"
gameScore.text = "Score:0"
gameScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.right
gameScore.fontSize = 20
gameScore.position = CGPoint(x: frame.maxX - 20, y: frame.maxY - 26)
gameScore.zPosition = 30
addChild(gameScore)
let pauseButton = SKLabelNode(fontNamed: "Arial")
pauseButton.name = "pauseButton"
pauseButton.text = "PAUSE"
pauseButton.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.left
pauseButton.fontSize = 20
pauseButton.position = CGPoint(x: 20, y: frame.maxY - 26)
pauseButton.zPosition = 30
addChild(pauseButton)
gameRunning = true
}
func didBeginContact(contact: SKPhysicsContact) {
print("contact")
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
// 2
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 3
if firstBody.categoryBitMask == PuppyCategory && secondBody.categoryBitMask == GroundCategory {
print("Hit bottom. First contact has been made.")
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
if gameRunning {
let gameScore = childNode(withName: "GameScore") as? SKLabelNode
gameScore?.text = "Score:\(playerScore)"
let currentTick:Int = Int(ceil(currentTime))
if lastTick < currentTick {
lastTick = currentTick
}
if (lastSpawnTime + spawnDelay) < currentTick {
// Time to Spawn new Bad Guy
generateThrowable()
lastSpawnTime = currentTick
}
}
}
}
I haven't checked other parts. (Your code still needs plenty of resources...)
But this line:
func didBeginContact(contact: SKPhysicsContact) {
needs to be changed as:
func didBegin(_ contact: SKPhysicsContact) {
in Swift 3. (Which is suggested by Xcode, with just typing didBegin.)
Please try.

How to save a high score with SpriteKit?

Im starting to learn how to code and i have no clue how to save the score to stay as a high score. any help will be appreciated! i already tried and tried but i can't manage to get it right. at this point i don't know what to do.
class Game: SKScene, SKPhysicsContactDelegate {
let Ball = SKSpriteNode(imageNamed: "Red.png")
var QuitOption = SKLabelNode()
var ScoreLabel = SKLabelNode()
var timesecond = Int(60)
var locked = false
var loseOption = SKLabelNode()
var scorePoints = SKLabelNode()
var score = Int()
var highScore = SKLabelNode()
let whiteBall = SKSpriteNode(imageNamed: "fingerPointingDown.png")
struct PhysicsCategory {
static let Ball: UInt32 = 0b1
static let whiteBall: UInt32 = 0b10
}
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.whiteColor() // background for the display
self.physicsWorld.gravity = CGVectorMake(0, -9.8)
self.physicsWorld.contactDelegate = self
let SceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
SceneBody.friction = 0
self.physicsBody = SceneBody
scorePoints = SKLabelNode(fontNamed: "Noteworthy-Light")
scorePoints.text = "0"
scorePoints.fontColor = SKColor.blackColor()
scorePoints.fontSize = 35
scorePoints.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*1 - 120)
scorePoints.name = "Points"
scorePoints.hidden = true
addChild(scorePoints)
Ball.size = CGSize(width: 82, height: 82)
Ball.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.1 - 60)
Ball.physicsBody = SKPhysicsBody(circleOfRadius: 41)
Ball.physicsBody?.affectedByGravity = true
Ball.physicsBody?.density = 10
Ball.physicsBody?.restitution = 0.1
Ball.physicsBody?.linearDamping = 0
Ball.name = "Ball"
Ball.physicsBody?.usesPreciseCollisionDetection = true
Ball.physicsBody?.categoryBitMask = PhysicsCategory.Ball
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.whiteBall
Ball.physicsBody?.collisionBitMask = PhysicsCategory.whiteBall
self.addChild(Ball)
QuitOption.text = "Quit"
QuitOption.fontName = "Noteworthy-Light"
QuitOption.fontColor = SKColor.purpleColor()
QuitOption.fontSize = 35
QuitOption.position = CGPoint(x: self.frame.size.width/2 - 160, y: self.frame.size.height*1 - 110)
QuitOption.name = "Quit"
addChild(QuitOption)
ScoreLabel = SKLabelNode(fontNamed: "Noteworthy-Light")
ScoreLabel.fontColor = SKColor.redColor()
ScoreLabel.fontSize = 35 // The + will move it to the right side and - to the left side for more accuracy.
ScoreLabel.position = CGPoint(x: self.frame.size.width/2 + 160, y: self.frame.size.height/1 - 115) // position of ScoreLabelNode
ScoreLabel.name = "Score+"
ScoreLabel.hidden = false
self.addChild(ScoreLabel)
whiteBall.size = CGSize(width: 55, height: 55)
whiteBall.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.8 - 30)
whiteBall.name = "whiteBall"
whiteBall.physicsBody = SKPhysicsBody(circleOfRadius: 25)
whiteBall.physicsBody?.dynamic = false
whiteBall.physicsBody?.restitution = 0.1
whiteBall.physicsBody?.usesPreciseCollisionDetection = true
whiteBall.physicsBody?.categoryBitMask = PhysicsCategory.whiteBall
whiteBall.physicsBody?.contactTestBitMask = PhysicsCategory.Ball
whiteBall.physicsBody?.collisionBitMask = PhysicsCategory.Ball
self.addChild(whiteBall)
}
// Making the ball jump after user touches ball
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
var touch = touches.first as! UITouch
var location = touch.locationInNode(self)
var node = self.nodeAtPoint(location)
if (node.name == "Quit"){
let myScene = GameScene(size: self.size)
myScene.scaleMode = scaleMode
let reveal = SKTransition.fadeWithDuration(1)
self.view?.presentScene(myScene, transition: reveal)
}
if (node.name == "Ball"){
for touch: AnyObject in touches {
Ball.physicsBody?.allowsRotation = true
Ball.physicsBody?.velocity = CGVectorMake(0, 0)
Ball.physicsBody?.applyImpulse(CGVectorMake(0, 450))
}
}
if(!self.locked){
self.locked = true
var actionrun = SKAction.waitForDuration(0.5)
var actionwait = SKAction.runBlock({
self.timesecond--
if self.timesecond == 60 {self.timesecond = 0}
self.ScoreLabel.text = "\(self.timesecond)"
if (self.timesecond == 0){
let myScene = WT(size: self.size)
myScene.scaleMode = self.scaleMode
let reveal = SKTransition.fadeWithDuration(1)
self.view?.presentScene(myScene, transition: reveal)
}
})
let loopAction = SKAction.repeatAction(SKAction.sequence([actionwait, actionrun]), count: 60)
ScoreLabel.runAction(loopAction, withKey: "scoreAction")
}
}
func didBeginContact(contact: SKPhysicsContact) {
let collision = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if collision == PhysicsCategory.Ball | PhysicsCategory.whiteBall {
score++
scorePoints.text = "Score: \(score)"
scorePoints.hidden = false
}
}
}
The simplest way is to use NSUserDefaults.
NSUserDefaults.standardUserDefaults().setInteger(highScore, forKey: "high_score")
NSUserDefaults.synchronize() // must be used to save
You can then load the score when needed
let highScore: Int = NSUserDefaults.standardUserDefaults().integerForKey("high_score")
You can access NSUserDefaults from anywhere, saving and loading as needed.
If you have more global player state, create an object for it and you could serialize the object by making it conform to NSCoding protocol.
You would need to implement the encode and decode functions, that save aand load your object's properties.

how can i save the high score?

Before i get any help i want to clarify that Im not an expert as you'll see. I'm a complete beginner in programming. now with that said.
How can i manage to save the high score after the game ends? in the following code I'm using NSUserDefaults but I'm having a problem in it that i can't fix. once i run the game and i get a score of 30 once the countdown hits 0 for example and then i try to play it again and i get a 12 for example it automatically 12 is the new high score to 12 which is totatly wrong but i can't fix it.
class Game: SKScene, SKPhysicsContactDelegate {
let Ball = SKSpriteNode(imageNamed: "Red.png")
var QuitOption = SKLabelNode()
var ScoreLabel = SKLabelNode()
var timesecond = Int(60)
var locked = false
var loseOption = SKLabelNode()
var scorePoints = SKLabelNode()
var score = Int()
let whiteBall = SKSpriteNode(imageNamed: "fingerPointingDown.png")
var caseForScoreOne = SKLabelNode()
var caseForScoreTwo = SKLabelNode()
struct PhysicsCategory {
static let Ball: UInt32 = 0b1
static let whiteBall: UInt32 = 0b10
}
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.whiteColor() // background for the display
self.physicsWorld.gravity = CGVectorMake(0, -9.8)
self.physicsWorld.contactDelegate = self
let SceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
SceneBody.friction = 0
self.physicsBody = SceneBody
scorePoints = SKLabelNode(fontNamed: "Noteworthy-Light")
scorePoints.text = "0"
scorePoints.fontColor = SKColor.blackColor()
scorePoints.fontSize = 35
scorePoints.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*1 - 120)
scorePoints.name = "Points"
addChild(scorePoints)
Ball.size = CGSize(width: 82, height: 82)
Ball.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.1 - 60)
Ball.physicsBody = SKPhysicsBody(circleOfRadius: 41)
Ball.physicsBody?.affectedByGravity = true
Ball.physicsBody?.density = 10
Ball.physicsBody?.restitution = 0.1
Ball.physicsBody?.linearDamping = 0
Ball.name = "Ball"
Ball.physicsBody?.usesPreciseCollisionDetection = true
Ball.physicsBody?.categoryBitMask = PhysicsCategory.Ball
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.whiteBall
Ball.physicsBody?.collisionBitMask = PhysicsCategory.whiteBall
self.addChild(Ball)
QuitOption.text = "Quit"
QuitOption.fontName = "Noteworthy-Light"
QuitOption.fontColor = SKColor.purpleColor()
QuitOption.fontSize = 35
QuitOption.position = CGPoint(x: self.frame.size.width/2 - 160, y: self.frame.size.height*1 - 110)
QuitOption.name = "Quit"
addChild(QuitOption)
ScoreLabel = SKLabelNode(fontNamed: "Noteworthy-Light")
ScoreLabel.fontColor = SKColor.redColor()
ScoreLabel.fontSize = 35 // The + will move it to the right side and - to the left side for more accuracy.
ScoreLabel.position = CGPoint(x: self.frame.size.width/2 + 160, y: self.frame.size.height/1 - 115) // position of ScoreLabelNode
ScoreLabel.name = "Score+"
ScoreLabel.hidden = false
self.addChild(ScoreLabel)
whiteBall.size = CGSize(width: 55, height: 55)
whiteBall.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.8 - 30)
whiteBall.name = "whiteBall"
whiteBall.physicsBody = SKPhysicsBody(circleOfRadius: 25)
whiteBall.physicsBody?.dynamic = false
whiteBall.physicsBody?.restitution = 0.1
whiteBall.physicsBody?.usesPreciseCollisionDetection = true
whiteBall.physicsBody?.categoryBitMask = PhysicsCategory.whiteBall
whiteBall.physicsBody?.contactTestBitMask = PhysicsCategory.Ball
whiteBall.physicsBody?.collisionBitMask = PhysicsCategory.Ball
self.addChild(whiteBall)
caseForScoreOne = SKLabelNode(fontNamed: "Noteworthy-Light")
caseForScoreOne.fontColor = SKColor.blackColor()
caseForScoreOne.fontSize = 25
caseForScoreOne.position = CGPoint(x: self.frame.size.width/2 - 160, y: self.frame.size.height*1 - 175)
caseForScoreOne.name = "caseOne"
addChild(caseForScoreOne)
caseForScoreTwo = SKLabelNode(fontNamed: "Noteworthy-Light")
caseForScoreTwo.fontColor = SKColor.blackColor()
caseForScoreTwo.fontSize = 25
caseForScoreTwo.position = CGPoint(x: self.frame.size.width/2 + 160, y: self.frame.size.height/1 - 175)
caseForScoreTwo.name = "caseTwo"
addChild(caseForScoreTwo)
}
// Making the ball jump after user touches ball
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
var touch = touches.first as! UITouch
var location = touch.locationInNode(self)
var node = self.nodeAtPoint(location)
if (node.name == "Quit"){
let myScene = GameScene(size: self.size)
myScene.scaleMode = scaleMode
let reveal = SKTransition.fadeWithDuration(1)
self.view?.presentScene(myScene, transition: reveal)
}
if (node.name == "Ball"){
for touch: AnyObject in touches {
Ball.physicsBody?.allowsRotation = true
Ball.physicsBody?.velocity = CGVectorMake(0, 0)
Ball.physicsBody?.applyImpulse(CGVectorMake(0, 450))
}
}
if(!self.locked){
self.locked = true
var actionrun = SKAction.waitForDuration(0.5)
var actionwait = SKAction.runBlock({
self.timesecond--
if self.timesecond == 60 {self.timesecond = 0}
self.ScoreLabel.text = "\(self.timesecond)"
if (self.timesecond == 0){
self.saveHighScore(0)
if self.score > self.highScore() {
self.saveHighScore(self.score)
self.caseForScoreTwo.text = "N.H.S = " + self.highScore().description
} else if (self.score > self.highScore()) {
self.caseForScoreOne.text = "N.H.S = " + self.score.description
}
}
})
let loopAction = SKAction.repeatAction(SKAction.sequence([actionwait, actionrun]), count: 60)
ScoreLabel.runAction(loopAction, withKey: "scoreAction")
}
}
func didBeginContact(contact: SKPhysicsContact) {
let collision = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if collision == PhysicsCategory.Ball | PhysicsCategory.whiteBall {
score++
scorePoints.text = "Score: \(score)"
}
}
func saveHighScore(high:Int) {
NSUserDefaults.standardUserDefaults().setInteger(high, forKey: "highscore")
}
func highScore() -> Int {
return NSUserDefaults.standardUserDefaults().integerForKey("highscore")
}
func resetHighScore() {
NSUserDefaults.standardUserDefaults().removeObjectForKey("highscore")
}
}
func saveHighScore(high:Int) {
if high > highScore() {
NSUserDefaults().setInteger(high, forKey: "highscore")
println("highscore saved")
} else {
println("not a highscore")
}
}

How can i make the lose label to appear once the timer hits zero?

I'm a beginner in coding and I need help in the following code. I'm trying to make the "You Lose!" label appear after the timer hits zero, but when I try to do it; it doesn't show anything. Please help me!
class Game: SKScene {
let Ball = SKSpriteNode(imageNamed: "Red.png")
var QuitOption = SKLabelNode()
var ScoreLabel = SKLabelNode()
var timesecond = Int(60)
var locked = false
var loseOption = SKLabelNode()
var winOption = SKLabelNode()
let whiteBall = SKSpriteNode(imageNamed: "whiteDot")
let showMessage = SKLabelNode()
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.whiteColor() // background for the display
self.physicsWorld.gravity = CGVectorMake(0, -9.8)
let SceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
SceneBody.friction = 0
self.physicsBody = SceneBody
Ball.size = CGSize(width: 82, height: 82)
Ball.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.1)
Ball.physicsBody = SKPhysicsBody(circleOfRadius: 42)
Ball.physicsBody?.affectedByGravity = true
Ball.physicsBody?.density = 10
Ball.physicsBody?.restitution = 0.1
Ball.physicsBody?.linearDamping = 0
Ball.name = "Ball"
self.addChild(Ball)
QuitOption.text = "Quit"
QuitOption.fontName = "Noteworthy-Light"
QuitOption.fontColor = SKColor.redColor()
QuitOption.fontSize = 35
QuitOption.position = CGPoint(x: self.frame.size.width/2 - 160, y: self.frame.size.height*1 - 110)
QuitOption.name = "Quit"
addChild(QuitOption)
ScoreLabel = SKLabelNode(fontNamed: "Noteworthy-Light")
ScoreLabel.fontColor = SKColor.redColor()
ScoreLabel.fontSize = 35 // The + will move it to the right side and - to the left side for more accuracy.
ScoreLabel.position = CGPoint(x: self.frame.size.width/2 + 160, y: self.frame.size.height/1 - 115) // position of ScoreLabelNode
ScoreLabel.name = "Score+"
ScoreLabel.hidden = false
self.addChild(ScoreLabel)
whiteBall.size = CGSize(width: 55, height: 55)
whiteBall.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.8)
whiteBall.name = "whiteBall"
self.addChild(whiteBall)
showMessage.fontName = "Noteworthy-Light"
showMessage.fontSize = 55
showMessage.fontColor = SKColor.whiteColor()
showMessage.text = "YOU LOSE!"
showMessage.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.7)
showMessage.zPosition = 100
showMessage.hidden = true
showMessage.name = "show Message"
self.addChild(showMessage)
}
// Making the ball jump after user touches ball
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
var touch = touches.first as! UITouch
var location = touch.previousLocationInNode(self)
// var location = touch.locationInNode(self)
var node = self.nodeAtPoint(location)
if (node.name == "Quit"){
let myScene = GameScene(size: self.size)
myScene.scaleMode = scaleMode
let reveal = SKTransition.fadeWithDuration(1)
self.view?.presentScene(myScene, transition: reveal)
}
if (node.name == "Ball"){
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
Ball.physicsBody?.allowsRotation = true
Ball.physicsBody?.velocity = CGVectorMake(0, 0)
Ball.physicsBody?.applyImpulse(CGVectorMake(0, 450))
}
}
if(!self.locked){
self.locked = true
var actionrun = SKAction.waitForDuration(0.5)
var actionwait = SKAction.runBlock({
self.timesecond--
if self.timesecond == 60 {self.timesecond = 0}
self.ScoreLabel.text = "\(self.timesecond)"})
let loopAction = SKAction.repeatAction(SKAction.sequence([actionwait, actionrun]), count: 60)
ScoreLabel.runAction(loopAction, withKey: "scoreAction")
if (timesecond == 0){
showMessage.hidden = false
}
}
}
}
Your code:
if (timesecond == 0){
showMessage.hidden = false
}
... should be in the block that runs every second:
var actionwait = SKAction.runBlock({
self.timesecond--
if self.timesecond == 60 {self.timesecond = 0}
self.ScoreLabel.text = "\(self.timesecond)"
if (self.timesecond == 0){
showMessage.hidden = false
}
})
let loopAction = SKAction.repeatAction(SKAction.sequence([actionwait, actionrun]), count: 60)
ScoreLabel.runAction(loopAction, withKey: "scoreAction")

Resources