如何使用Swift将游戏的高分保存在Leaderboard上?

时间:2015-08-21 16:20:54

标签: swift sprite-kit game-center xcode7

我使用SpriteKit和Xcode 7 beta制作了游戏。我试图把GameCenter和排行榜放在一边,但问题是排行榜中的得分不会改变它一直保持0(游戏的高分赢得并排在排行榜中)并且我不知道如何解决它。我使用了3个不同的文件: GameScene.swift GameViewController.swift 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)"
 }
}

我认为问题出在代码中的GameViewController.swift文件中:

@IBAction func leaderboard(sender: UIButton) {

    saveHighscore(scoreManager.score)

    scoreManager.increment() //<-- Here

    showLeader()

}

也许我没有把它放在正确的地方

    scoreManager.increment()

3 个答案:

答案 0 :(得分:4)

我看到一些可能导致问题的因素。首先是这种方法......

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

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

我没有看到你设置的任何地方,所以把它拉出来不会有多大帮助。我在saveHighscore:function bellow中将保存添加到默认值。

第二是......

saveHighscore(scoreManager.score)

scoreManager.increment() //<-- Here

showLeader()

在保存分数之前,您应该增加。

我会尝试添加这些日志以查看这是否有帮助...

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")
            }
        })
    }
}

希望在日志中打印或不打印的内容加上实际保存默认值会有所帮助。祝好运。

修改

所以问题的根源在于你的VC中有scoreManager(这是一个PointsLabel),但你也有一个在你的场景中。在你的场景中你正在更新得分和生活是好的。当您点击按钮时,您实际上从VC中的标签获得的分数没有得到更新。所以你真正需要的是在你的场景中找到那个标签以取出分数。

所以我能想到的最简单的方法就是让代码发生变化,以便对代码进行少量更改...

完全删除此行...

var scoreManager = PointsLabel(num: 0)

并将您的操作更改为此...

@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()

}

希望能解决所有问题=)

答案 1 :(得分:1)

在您的游戏中,您需要增加分数并在用户得分时将分数发送到游戏中心。我不确定你的游戏是如何运作的,但每当他们获得一个积分时你需要更新分数并将该分数发送到游戏中心并更新标签。点击排行榜按钮时,您无法更新分数。我不确定我是否清楚,所以问你是否需要澄清或帮助。

答案 2 :(得分:0)

听起来您需要使用核心数据,它是您用来在应用中保存数据的方法。我不太了解它,所以我只能指出一些可能有用的资源:

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