> 原文:http://www.jianshu.com/p/da7f53fab298
作者:[PMST](http://www.jianshu.com/users/596f2ba91ce9/latest_articles)
課時7中實現了得分機制,當你越戰越勇,得分也蹭蹭地往上加,不過馬有失蹄,人有失足,總會不小心失敗,這時候就要結算你的勞動成果了:通常都是告知游戲結束,得分幾何,最好成績等等信息。咱們游戲是這么設計的:

**本文任務:**
* 當游戲結束時呈現上圖的內容。
**思路:**
* 簡單來說就是實例化幾個特定紋理(你可以理解為照片*image*)的精靈,然后按照特定布局放置到屏幕中,是不是灰常簡單呢?
## 01.使用NSUserDefaults來保存數據
使用*NSUserDefaults*用于持久性的保存得分記錄是一個明智的決定,我們不可能為了存一個數據而使用諸如`Core Data`或者`Sqlite`等數據庫。
### 1-1 從NSUserDefault中讀取分數
請在*GameScene*類中添加一個新方法,用于讀取游戲記錄得分:
~~~
func bestScore()->Int{
return NSUserDefaults.standardUserDefaults().integerForKey("BestScore")
}
~~~
可以看到方法中為最高得分設置了名為"BestScore"的鍵。
### 1-2 在NSUserDefault中設置分數
有讀取自然有寫,請在*bestScore()*方法下方添加一個新方法:
~~~
func setBestScore(bestScore:Int){
NSUserDefaults.standardUserDefaults().setInteger(bestScore, forKey: "BestScore")
NSUserDefaults.standardUserDefaults().synchronize()
}
~~~
## 02.構建得分面板
得分面板如文中給出圖片布局,工程量還是蠻大的,不過我會一步一步講解,無需擔心一口吃撐的情況。
首先請找到*setupLabel*方法,在它下方聲明咱們的設置得分面板的函數,取名為`setupScorecard()`:
~~~
func setupScorecard() {
//1
if score > bestScore() {
setBestScore(score)
}
//...等下添加其他內容
}
~~~
* 首先調用`bestScore()`取到歷史最高得分,與本回合得分比較,倘若這次“走狗屎運”得了高分,咱們就要更新歷史最高紀錄,也就是調用`setBestScore(score)`方法。
接著,著手添加得分面板的精靈,內容有點多,請注意別碼錯:
~~~
func setupScorecard() {
if score > bestScore() {
setBestScore(score)
}
// 1 得分面板背景
let scorecard = SKSpriteNode(imageNamed: "ScoreCard")
scorecard.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
scorecard.name = "Tutorial"
scorecard.zPosition = Layer.UI.rawValue
worldNode.addChild(scorecard)
// 2 本次得分
let lastScore = SKLabelNode(fontNamed: kFontName)
lastScore.fontColor = SKColor(red: 101.0/255.0, green: 71.0/255.0, blue: 73.0/255.0, alpha: 1.0)
lastScore.position = CGPoint(x: -scorecard.size.width * 0.25, y: -scorecard.size.height * 0.2)
lastScore.text = "\(score)"
scorecard.addChild(lastScore)
// 3 最好成績
let bestScoreLabel = SKLabelNode(fontNamed: kFontName)
bestScoreLabel.fontColor = SKColor(red: 101.0/255.0, green: 71.0/255.0, blue: 73.0/255.0, alpha: 1.0)
bestScoreLabel.position = CGPoint(x: scorecard.size.width * 0.25, y: -scorecard.size.height * 0.2)
bestScoreLabel.text = "\(self.bestScore())"
scorecard.addChild(bestScoreLabel)
// 4 游戲結束
let gameOver = SKSpriteNode(imageNamed: "GameOver")
gameOver.position = CGPoint(x: size.width/2, y: size.height/2 + scorecard.size.height/2 + kMargin + gameOver.size.height/2)
gameOver.zPosition = Layer.UI.rawValue
worldNode.addChild(gameOver)
// 5 ok按鈕背景以及ok標簽
let okButton = SKSpriteNode(imageNamed: "Button")
okButton.position = CGPoint(x: size.width * 0.25, y: size.height/2 - scorecard.size.height/2 - kMargin - okButton.size.height/2)
okButton.zPosition = Layer.UI.rawValue
worldNode.addChild(okButton)
let ok = SKSpriteNode(imageNamed: "OK")
ok.position = CGPoint.zeroPoint
ok.zPosition = Layer.UI.rawValue
okButton.addChild(ok)
// 6 share按鈕背景以及share標簽
let shareButton = SKSpriteNode(imageNamed: "Button")
shareButton.position = CGPoint(x: size.width * 0.75, y: size.height/2 - scorecard.size.height/2 - kMargin - shareButton.size.height/2)
shareButton.zPosition = Layer.UI.rawValue
worldNode.addChild(shareButton)
let share = SKSpriteNode(imageNamed: "Share")
share.position = CGPoint.zeroPoint
share.zPosition = Layer.UI.rawValue
shareButton.addChild(share)
}
~~~
當你碼完了這一段超長代碼之后,你會松一口氣,現在還有一步就能享受勝利的果實了!!
想想我們時候什么需要顯示這個得分面板。*Player*掉落失敗的時候,對嗎?請找到`switchToShowScore()`方法,在最下方調用`setupScorecard()`,點擊運行,過幾個障礙物,然后自由落體,看看是否良好地顯示了得分面板。
Good Job!顯示本次得分,歷史最高紀錄以及選項按鈕——不過此時并沒有什么卵用。
你有木有發現得分面板“毫無征兆”地就出現在了場景中央,來加個動畫吧!!!
##03.為得分面板添加動畫
請回到原先的`setupScorecard()`方法,繼續再下方添加動畫代碼:
~~~
//=== 添加一個常量 用于定義動畫時間 ====
let kAnimDelay = 0.3
func setupScorecard() {
//。。。。。。
//==== 以下是新添加的內容 =====
gameOver.setScale(0)
gameOver.alpha = 0
let group = SKAction.group([
SKAction.fadeInWithDuration(kAnimDelay),
SKAction.scaleTo(1.0, duration: kAnimDelay)
])
group.timingMode = .EaseInEaseOut
gameOver.runAction(SKAction.sequence([
SKAction.waitForDuration(kAnimDelay),
group
]))
scorecard.position = CGPoint(x: size.width * 0.5, y: -scorecard.size.height/2)
let moveTo = SKAction.moveTo(CGPoint(x: size.width/2, y: size.height/2), duration: kAnimDelay)
moveTo.timingMode = .EaseInEaseOut
scorecard.runAction(SKAction.sequence([
SKAction.waitForDuration(kAnimDelay * 2),
moveTo
]))
okButton.alpha = 0
shareButton.alpha = 0
let fadeIn = SKAction.sequence([
SKAction.waitForDuration(kAnimDelay * 3),
SKAction.fadeInWithDuration(kAnimDelay)
])
okButton.runAction(fadeIn)
shareButton.runAction(fadeIn)
let pops = SKAction.sequence([
SKAction.waitForDuration(kAnimDelay),
popAction,
SKAction.waitForDuration(kAnimDelay),
popAction,
SKAction.waitForDuration(kAnimDelay),
popAction,
SKAction.runBlock(switchToGameOver)
])
runAction(pops)
}
~~~
點擊運行,玩耍吧!
> 注意: 我發現了一個BUG,倘若游戲一開始就使得它下落觸碰地面,彈出的得分面板*share*標簽放置位置是錯誤的,因為它的背景以`let shareButton = SKSpriteNode(imageNamed: "Button")`?返回的是一個精靈`size=0`,讓我百思不得其解。希望找到問題的朋友可以告知我。