如何使用 Swift 将游戏的高分保存在排行榜上?
Posted
技术标签:
【中文标题】如何使用 Swift 将游戏的高分保存在排行榜上?【英文标题】:How to make High Score of game to be saved on Leaderboard, with Swift? 【发布时间】:2015-08-21 16:20:54 【问题描述】:我使用 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()
【问题讨论】:
【参考方案1】:嗯,我看到了一些可能导致该问题的事情。首先是这个方法……
func loadHighscore()
let defaults = NSUserDefaults.standardUserDefaults()
let highscoreLabel = childNodeWithName("highscoreLabel") as! PointsLabel
highscoreLabel.setTo(defaults.integerForKey("highscore"))
我没有看到您设置的任何地方,因此将其拉出不会有太大帮助。我在下面的 saveHighscore: 函数中将保存添加到默认值。
其次是……
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)它在我这样做之前运行良好,所以这又产生了一个问题。第二高分没有像以前那样保存到排行榜。 @EminEmini 正如我之前所说,您需要查看您的日志。您是否获得“身份验证”您是否正确打印出“ScoreReporter”?是否“报告正确退出”? authenticated ScoreReporter:在您的游戏中,您需要在用户得分时增加分数并将分数发送到 Game Center。我不确定您的游戏是如何运作的,但是每当他们应该获得积分时,您都需要更新分数并将该分数发送到游戏中心并更新标签。点击排行榜按钮时,您无法更新分数。我不确定我是否清楚,所以请询问您是否需要澄清或帮助。
【讨论】:
是的,我知道了,关于分数、高分和排行榜的一切都是有问题的。【参考方案3】:听起来你需要使用核心数据,它是你用来在应用程序中保存数据的东西。我对此了解不多,所以我只能向您指出一些可能有帮助的资源:
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
【讨论】:
这里不需要使用CoreData,因为OP已经使用NSUserDefaults来实现持久化了。以上是关于如何使用 Swift 将游戏的高分保存在排行榜上?的主要内容,如果未能解决你的问题,请参考以下文章