I have been working on my xcode project for a couple of weeks now using Xcode and swift. Today when I started running the simulator my highScore was set to 0. This was the first time, it had always kept score. Does this have anything to do with the simulator or is something wrong with my code. I of course don't want the user to use my app if the highScore can reset to 0 at any given time.
class GameScene: SKScene {
let labelHighScore = SKLabelNode()
var highScore = 0
override func didMoveToView(view: SKView) {
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
if(HighscoreDefault.valueForKey("Highscore") != nil) {
highScore = HighscoreDefault.valueForKey("Highscore") as! NSInteger
labelHighScore.text = NSString(format: "%i", highScore) as String
}
labelHighScore.fontSize = 70
labelHighScore.position = CGPointMake(frame.midX, frame.midY + 305)
labelHighScore.fontColor = UIColor.blackColor()
self.addChild(labelHighScore)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if ball != blackB && ball.texture == blackB.texture {
score += 1
labelScore.text = String(score)
if(score > highScore) {
highScore = score
labelHighScore.text = String(highScore)
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
HighscoreDefault.setValue(highScore, forKey: "Highscore")
HighscoreDefault.synchronize()
}
}
Unless your using the same device it would not keep the same user defaults. If you have always used the simulator they are known to reset from time to time. My suggestions would be to explicitly set the high score's default and run. comment out the code that sets the default and re run. It should maintain that value.
Related
I know I'm close in getting the getting the score to increment in my game.
When I explicitly change the code to add a integer (5 for example) instead of "%d", the score shows in the HUD when a coin is touched :
func didBeginContact(contact: SKPhysicsContact) {
lblScore.text = String(format: "%d", GameState.sharedInstance.score)
}
to:
func didBeginContact(contact: SKPhysicsContact) {
lblScore.text = String(format: "5", GameState.sharedInstance.score)
}
However if I leave the "%d", then nothing happens. I'm not sure how to increment the score in the HUD or where to make changes.
Here's the rest of the code.
GameScene.swift:
struct PhysicsCategory {
static let None: UInt32 = 0
static let Player: UInt32 = 0b1
static let CoinNormal: UInt32 = 0b1000
static let CoinSpecial: UInt32 = 0b10000
}
class GameScene: SKScene, SKPhysicsContactDelegate {
// HUD
var hudNode: SKNode!
var lblScore: SKLabelNode!
var lblCoins: SKLabelNode!
override func didMoveToView(view: SKView) {
// HUD
hudNode = SKNode()
hudNode.zPosition = 1000
cameraNode.addChild(hudNode)
// Coins
// 1
let coin = SKSpriteNode(imageNamed: "powerup05_1")
coin.position = convertPoint(CGPoint(x: 300, y: self.size.height-100), toNode: cameraNode)
coin.zPosition = 1000
hudNode.addChild(coin)
// 2
lblCoins = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
lblCoins.fontSize = 70
lblCoins.fontColor = SKColor.whiteColor()
lblCoins.position = convertPoint(CGPoint(x: 375, y: self.size.height-100), toNode: cameraNode)
lblCoins.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
lblCoins.zPosition = 1000
// 3
lblCoins.text = String(format: "X %d", GameState.sharedInstance.coins)
hudNode.addChild(lblCoins)
// Score
// 4
lblScore = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
lblScore.fontSize = 70
lblScore.fontColor = SKColor.whiteColor()
lblScore.position = convertPoint(CGPoint(x: self.size.width-325, y: self.size.height-100), toNode: cameraNode)
lblScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Right
lblScore.zPosition = 1000
// 5
lblScore.text = "0"
hudNode.addChild(lblScore)
}
}
func didBeginContact(contact: SKPhysicsContact) {
lblScore.text = String(format: "%d", GameState.sharedInstance.score)
}
GameState.swift:
class GameState {
var score: Int
var highScore: Int
var coins: Int
init() {
// Init
score = 0
highScore = 0
coins = 0
// Load game state
let defaults = NSUserDefaults.standardUserDefaults()
highScore = defaults.integerForKey("highScore")
coins = defaults.integerForKey("coins")
}
func saveState() {
// Update highScore if the current score is greater
highScore = max(score, highScore)
score = max(score, highScore)
// Store in user defaults
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(highScore, forKey: "highScore")
defaults.setInteger(coins, forKey: "coins")
NSUserDefaults.standardUserDefaults().synchronize()
}
class var sharedInstance: GameState {
struct Singleton {
static let instance = GameState()
}
return Singleton.instance
}
}
As I can see you are using GameState.sharedInstance.score to store a score. But you never update it. You have to increment the score each time when player scores. This part:
lblScore.text = String(format: "%d", GameState.sharedInstance.score)
only reads from a score variable.
Also this part doesn't make sense:
highScore = max(score, highScore)
score = max(score, highScore) //remove this
score variable is not the same as highscore variable.
I was able to increment the score by this line:
GameState.sharedInstance.score += 1
Or replace 1 with another number by how many points you want to increment.
I'm trying to reset my high score in my Sprite Kit game, but am having some trouble.
Now, I'm able to reset the labels in the HUD back to zero, but when the game starts again the scores in the labels jump back up to where they were before because they are stored in NSUserDefaults.
I'm resetting the labels like so:
override func didMoveToView(view: SKView) {
lblCoins.text = "0"
lblScore.text = "0"
}
I'm trying to reset NSUserDefaults like so:
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "highScore")
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "coins")
NSUserDefaults.standardUserDefaults().synchronize()
I've tried placing this block of code everywhere in my game, but can't seem to reset the score. The score will only reset if I completely reset the app.
Here are some functions I've tried placing:
override func didMoveToView(view: SKView) {
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "highScore")
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "coins")
NSUserDefaults.standardUserDefaults().synchronize()
}
On GameOver:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
...
case is GameOver:
let newScene = GameScene(fileNamed:"GameScene")
newScene!.scaleMode = .AspectFill
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
self.view?.presentScene(newScene!, transition: reveal)
self.saveHighScore("com.prismstudios.jumpingcarl.leaderboard", score: GameState.sharedInstance.highScore)
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "highScore")
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "coins")
NSUserDefaults.standardUserDefaults().synchronize()
default:
break
}
}
Here is where I'm adding the points in the GameScene:
func didBeginContact(contact: SKPhysicsContact) {
GameState.sharedInstance.highScore += 10
lblScore.text = String(format: "%d", GameState.sharedInstance.highScore)
GameState.sharedInstance.coins += 1
lblCoins.text = String(format: "%d", GameState.sharedInstance.coins)
}
The GameState class:
class GameState {
var score: Int
var highScore: Int
var coins: Int
init() {
// Init
score = 0
highScore = 0
coins = 0
// Load game state
let defaults = NSUserDefaults.standardUserDefaults()
highScore = defaults.integerForKey("highScore")
coins = defaults.integerForKey("coins")
}
func saveState() {
// Update highScore if the current score is greater
highScore = max(score, highScore)
// Store in user defaults
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(highScore, forKey: "highScore")
defaults.setInteger(coins, forKey: "coins")
NSUserDefaults.standardUserDefaults().synchronize()
}
class var sharedInstance: GameState {
struct Singleton {
static let instance = GameState()
}
return Singleton.instance
}
}
Anyone can help?
If you want to reset everything try this:
let defaults = `NSUserDefaults`.standardUserDefaults()
let appDomain: NSString = NSBundle.mainBundle().bundleIdentifier!
defaults.removePersistentDomainForName(appDomain as String)
If you just want to reset your highscore you have to choose the right "one". If you are making something like this:
defaults.setValue(123, forKey: "Highscore")
defaults.synchronize()
And then
defaults.setValue(0, forKey: "Highscore")
defaults.synchronize()
You have something like an array:
Highscore1 = defaults.objectForKey("Highscore")![0] as? Int //123
Highscore2 = defaults.objectForKey("Highscore")![1] as? Int //0
You are just adding more highscores... Try something like this:
func resetHighscore(){
let defaults = `NSUserDefaults`.standardUserDefaults()
defaults.removeObjectForKey("Highscore")
defaults.setValue(0, forKey: "Highscore")
defaults.synchronize()
}
OK I figured it out.
After, I post the score to Game Center, then I add GameState.sharedInstance.highScore = 0:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
switch gameState.currentState {
...
case is GameOver:
let newScene = GameScene(fileNamed:"GameScene")
newScene!.scaleMode = .AspectFill
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
self.view?.presentScene(newScene!, transition: reveal)
// Save high score to Game Center
self.saveHighScore("com.prismstudios.jumpingcarl.leaderboard", score: GameState.sharedInstance.highScore)
// Reset score and coins collected back to zero
GameState.sharedInstance.highScore = 0
GameState.sharedInstance.coins = 0
default:
break
}
}
I'm not really sure why it works this way and NSUserDefaults fails, but I know it has something to do with the fact that I have a GameState helper class.
I have these two UITextFields and the first texField subtracts the number from the second textField. It then takes the answer and puts it in my SKLabelNode. That works fine. But the problem Im having is that it doesn't save the label. When I quit the app and go back to it it doesnt save the value. What am I doing wrong with my code?
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in (touches as! Set<UITouch>) {
var defaults=NSUserDefaults.standardUserDefaults()
var save=defaults.integerForKey("saveCalories")
var touch: UITouch = touches.first as! UITouch
var location = touch.locationInNode(self)
var node = self.nodeAtPoint(location)
if let number1 = textFieldCaloriesIntake.text.toInt() {
if let number2 = textFieldCaloriesBurned.text.toInt() {
let subtract = number1 - number2
defaults.setInteger(subtract, forKey: "saveCalories")
var showTotalCalories = defaults.integerForKey("saveCalories")
totalCaloriesLabel.text = String(showTotalCalories)
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
}
Use this code for Swift
NSUserDefaults.standardUserDefaults().setValue(value, forKey:key)
Save example:
NSUserDefaults.standardUserDefaults().setValue(positionTextField.text!, forKey: "position")
Retrieve example:-
position!.text=NSUserDefaults.standardUserDefaults().stringForKey("position")
Note: remember the key for further retrievals
Save the text of the label in NSUserDefaultinstead
I got it to work by putting the code in the didMoveToView; it saves the label now.
Im trying to keep track of how many times the user loses in my game. So for every loss it goes up by 1. I also want to save it too so the user could see how many total times they lost. Right now the code I have it works the first time and goes to one but if I lose in the game after that it just stays at 1. What am I doing wrong? Thanks!
class level1: SKScene, SKPhysicsContactDelegate, GKGameCenterControllerDelegate {
var deathScore = 0
override func didMoveToView(view: SKView) {
var deathLabel = SKLabelNode()
deathLabel = SKLabelNode(fontNamed: "LadyIce-3D")
deathLabel.text = "100"
deathLabel.zPosition = 14
deathLabel.fontSize = 100
deathLabel.fontColor = SKColor.darkTextColor()
deathLabel.position = CGPointMake(self.size.width / 1.1, self.size.height / 1.4)
deathLabel.hidden = true
self.addChild(deathLabel)
}
if firstBody.categoryBitMask == HeroCategory && fourthBody.categoryBitMask == GameOverCategory {
deathScore++
deathLabel.hidden = false
let defaults = NSUserDefaults()
let saveDeaths = NSUserDefaults().integerForKey("saveNumberOfDeaths")
if(deathScore > saveDeaths)
{
NSUserDefaults().setInteger(saveDeaths, forKey: "saveNumberOfDeaths")
}
var showNumberOfDeaths = defaults.integerForKey("saveNumberOfDeaths")
deathLabel.text = String(showNumberOfDeaths)
}
}
You are declaring a new var deathScore everytime, initialized with 0 and incrementing it. It will always be 1.
UserDefaults.standard.set(UserDefaults.standard.integer(forKey: "saveNumberOfDeaths")+1, forKey: "saveNumberOfDeaths")
deathLabel.text = String(UserDefaults.standard.integer(forKey: "saveNumberOfDeaths"))
I have set a high score using NSUserDefaults where if the object makes contact with a block, the game ends. If the score is greater than the high score, it updates the high score with the new value.
How would I reset the high score back to zero with a button?
func didBeginContact(contact: SKPhysicsContact) {
if moving.speed > 0 {
if ( contact.bodyA.categoryBitMask & scoreCategory ) == scoreCategory || ( contact.bodyB.categoryBitMask & scoreCategory ) == scoreCategory {
// Balloon has contact with score entity
score++
scoreLabelNode.text = String(score)
// Add a little visual feedback for the score increment
scoreLabelNode.runAction(SKAction.sequence([SKAction.scaleTo(1.5, duration:NSTimeInterval(0.1)), SKAction.scaleTo(1.0, duration:NSTimeInterval(0.1))]))
} else {
moving.speed = 0
balloon.physicsBody?.collisionBitMask = blockCategory
NSUserDefaults.standardUserDefaults().integerForKey("highscore")
//Check if score is higher than NSUserDefaults stored value and change NSUserDefaults stored value if it's true
if score > NSUserDefaults.standardUserDefaults().integerForKey("highscore")
{
NSUserDefaults.standardUserDefaults().setInteger(score, forKey: "highscore")
NSUserDefaults.standardUserDefaults().synchronize()
}
NSUserDefaults.standardUserDefaults().integerForKey("highscore")
var highscoreShow = defaults.integerForKey("highscore")
highscoreLabelNode = SKLabelNode(fontNamed: "MarkerFelt-Wide")
highscoreLabelNode.position = CGPointMake(CGRectGetMidX(self.frame), 530)
highscoreLabelNode.zPosition = 10
highscoreLabelNode.fontSize = 18
highscoreLabelNode.text = "Highscore: \(highscoreShow)"
self.addChild(highscoreLabelNode)
gameoverLabelNode = SKLabelNode(fontNamed: "MarkerFelt-Wide")
gameoverLabelNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
gameoverLabelNode.zPosition = 10
gameoverLabelNode.text = "GameOver"
self.addChild(gameoverLabelNode)
returnBtn.position = CGPointMake(CGRectGetMidX(self.frame), 250)
returnBtn.zPosition = 5
returnBtn.setScale(0.5)
self.addChild(returnBtn)
println("end the game")
self.canRestart = true
}
}
}
To reset the high score back to zero all you need to use is:
//Sets the integer value for the key "highscore" to be equal to 0
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "highscore")
//Synchronizes the NSUserDefaults
NSUserDefaults.standardUserDefaults().synchronize()