4

I made a game using SpriteKit and Xcode 7 beta. I tried to put GameCenter and Leaderboard but the problem is that the score in leaderboard won't change it stay all the time 0 (High Score of game won't save in Leaderboard) and I don't know how to fix it. I'm using 3 different files: GameScene.swift, GameViewController.swift, and PointsLabel.swift.

GameScene.swift

func addPointsLabels() {
    let pointsLabel = PointsLabel(num: 0)
    pointsLabel.position = CGPointMake(30.0, view!.frame.size.height - 40)
    pointsLabel.name = "pointsLabel"
    addChild(pointsLabel)


    //High Score
    let highscoreLabel = PointsLabel(num: 0)
    highscoreLabel.name = "highscoreLabel"
    highscoreLabel.position = CGPointMake(view!.frame.size.width - 35, view!.frame.size.height - 40)
    addChild(highscoreLabel)
}


func loadHighscore() {
    let defaults = NSUserDefaults.standardUserDefaults()

    let highscoreLabel = childNodeWithName("highscoreLabel") as! PointsLabel
    highscoreLabel.setTo(defaults.integerForKey("highscore"))
}

GameViewController.swift:

import GameKit

class GameViewController: UIViewController,UIGestureRecognizerDelegate, GKGameCenterControllerDelegate {

var scoreManager = PointsLabel(num: 0)

override func viewDidLoad() {
    super.viewDidLoad()

    //initiate gamecenter
func authenticateLocalPlayer(){

    let localPlayer = GKLocalPlayer.localPlayer()

    localPlayer.authenticateHandler = {(GameViewController, error) -> Void in

        if (GameViewController != nil) {
            self.presentViewController(GameViewController!, animated: true, completion: nil)
        }

        else {
            print((GKLocalPlayer.localPlayer().authenticated))
        }
     }
  }
}

@IBAction func leaderboard(sender: UIButton) {

    saveHighscore(scoreManager.score)

    scoreManager.increment()

    showLeader()

}



//send high score to leaderboard
func saveHighscore(score:Int) {

    //check if user is signed in
    if GKLocalPlayer.localPlayer().authenticated {

        let scoreReporter = GKScore(leaderboardIdentifier: "Leaderboard_01")

        scoreReporter.value = Int64(score)

        let scoreArray: [GKScore] = [scoreReporter]

        GKScore.reportScores(scoreArray, withCompletionHandler: {error -> Void in
            if error != nil {
                print("error")
            }
        })
    }
}


    //shows leaderboard screen
    func showLeader() {
        let vc = self.view?.window?.rootViewController
        let gc = GKGameCenterViewController()
        gc.gameCenterDelegate = self
        vc?.presentViewController(gc, animated: true, completion: nil)
    }
}

//hides leaderboard screen
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController)
{
    gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)

}

PointsLabel.swift:

import Foundation
import UIKit
import SpriteKit

class PointsLabel: SKLabelNode {

var score:Int = 0

init(num: Int) {
    super.init()

    fontColor = UIColor.blackColor()
    fontSize = 30.0

    score = num
    text = "\(num)"
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func increment() {
    score++
    text = "\(score)"
}

func setTo(num: Int) {
    self.score = num
    text = "\(self.score)"
 }
}

I think the problem is in file GameViewController.swift in code:

@IBAction func leaderboard(sender: UIButton) {

    saveHighscore(scoreManager.score)

    scoreManager.increment() //<-- Here

    showLeader()

}

Maybe I didn't put it in right place

    scoreManager.increment()
Emm
  • 1,963
  • 2
  • 20
  • 51

3 Answers3

4

Well I see a couple things that can contribute to the issue. First is this method...

func loadHighscore() {
    let defaults = NSUserDefaults.standardUserDefaults()

    let highscoreLabel = childNodeWithName("highscoreLabel") as! PointsLabel
    highscoreLabel.setTo(defaults.integerForKey("highscore"))
}

I don't see anywhere you are setting that so pulling it out won't help much. I added the saving to defaults in the saveHighscore: function bellow.

Second is...

saveHighscore(scoreManager.score)

scoreManager.increment() //<-- Here

showLeader()

You should increment before you save your score.

I would try adding these logs to see if this helps...

func saveHighscore(score:Int) {

    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setInteger(score, forKey: "highscore")
    defaults.synchronize()

    //check if user is signed in
    if GKLocalPlayer.localPlayer().authenticated {

        println("authenticated")

        let scoreReporter = GKScore(leaderboardIdentifier: "Leaderboard_01")
        println("ScoreReporter: \(scoreReporter)")

        scoreReporter.value = Int64(score)

        let scoreArray: [GKScore] = [scoreReporter]

        GKScore.reportScores(scoreArray, withCompletionHandler: {error -> Void in
            if error != nil {
                print("error")
            }
            else{
                println("reported correctly")
            }
        })
    }
}

Hopefully what does or don't print out in the logs plus actually saving your defaults will help. Good luck.

Edit

So it appears the root of the problem is that you have scoreManager (which is a PointsLabel) in your VC but you also have one that is in your Scene. The one in your scene you are updating the score and life is good. When you hit the button you are actually getting the score from the label in your VC that isn't getting updated. So what you really need is to get to that label in your scene to pull out the score.

So the easiest way I can think of getting it to work properly with as little changes to your code is this…

Remove this line completely…

var scoreManager = PointsLabel(num: 0)

and change your action to this...

@IBAction func leaderboard(sender: UIButton) {

    let skView = self.view as! SKView
    let scene = skView.scene
    let scoreManager = scene.childNodeWithName("pointsLabel") as! PointsLabel

    saveHighscore(scoreManager.score)

    showLeader()

}

Hopefully that fixes everything =)

Skyler Lauren
  • 3,792
  • 3
  • 18
  • 30
  • I did as You said but is not working. 1st high score won't save it go back to 1 (weird why to 1) it work well before I did this so this made another problem. 2nd the high score is not saving to leaderboard as before. – Emm Sep 01 '15 at 10:18
  • @EminEmini as I stated before you will need to look at your logs. Are you getting "authenticated" are you getting "ScoreReporter" printing out correctly? Is "reported correctly logging out"? – Skyler Lauren Sep 01 '15 at 11:40
  • authenticated ScoreReporter: player:playerID:G:8359742824 alias:EminEmini98 rank:0 date:2015-09-01 12:50:57 +0000 value:0 formattedValue:(null) context:0x0 leaderboard:Leaderboard_01.1 group:(null) reported correctly Sep 1 14:51:16 MyApp[6735] : 14:51:16.853313 [NSLog]: plugin com.apple.GameCenterUI.GameCenterDashboardExtension invalidated – Emm Sep 01 '15 at 12:57
  • @EminEmini far as I can tell you are reporting the score. But you are likely reporting a score of 1 because you are not loading in previous score. Also what logging out that error at the end? Given it seems to be related to game center that could be part of your problem. – Skyler Lauren Sep 01 '15 at 23:03
  • Can You show me how to fix them, because I want to give to someone these 100Reputation. – Emm Sep 01 '15 at 23:20
  • @EminEmini you can try emailing me at skyler@spritekitalliance.com and I can try to help troubleshoot the issue. If I am able to figure it out I will update my answer so you can accept it and others can learn, but I don't think back and forth in comments is going to help at this point. – Skyler Lauren Sep 02 '15 at 00:08
  • I sent You a message. :) – Emm Sep 02 '15 at 11:58
1

In your game, you need to increment the score AND send the score to Game Center whenever the user scores a point. I'm not sure how your game works, but whenever they should be awarded a point you need to update the score and send that score to game center and update the label. You just can't update the score when the leaderboard button is tapped. I'm not sure if I was clear so ask if you need clarification or help.

TheCodeComposer
  • 725
  • 5
  • 17
  • Yes I got You, Everything what is about score, high score, and leaderboard is here in question. – Emm Sep 01 '15 at 10:28
0

It sounds like you need to use core data, it is what you use to save data in an app. I don't know to much about it so I can only point you to a few recourses that might help:

Apple Docs

Core Data relationships (swift)

Swift - Core Data Seeding Class

Check if property is set in Core Data?

How do I access and use an entity using Core Data

Community
  • 1
  • 1
Caleb Kleveter
  • 11,170
  • 8
  • 62
  • 92
  • Using CoreData here is not necessary , because OP already using NSUserDefaults to implement persistence. – Whirlwind Sep 01 '15 at 12:36