用Swift做個遊戲Lecture08 —— Show Me 得分面板!

課時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,讓我百思不得其解。希望找到問題的朋友可以告知我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章