iT邦幫忙

2021 iThome 鐵人賽

DAY 23
2
Mobile Development

從零開始的8-bit迷宮探險!Swift SpriteKit 遊戲開發實戰系列 第 23

從零開始的8-bit迷宮探險【Level 23】長老,這個水晶值多少錢?

「喂?」山姆拿起對講機,試著聯絡村子裡的長老。
「我在這座黑森林裡,找到很多水晶,這樣不知道可以賣多少錢?」山姆期待著長老的回應。
長老想了一下,露出慈祥(?)的微笑。
「這些水晶,我 50 收!」

今日目標

  • 計算水晶、魔幻水晶、香菇、擊退怪物的得分
  • 在遊戲中顯示得分

PS. 這裡是開發 iOS 手機遊戲的系列文,如果還沒看過之前 劇情 文章的朋友,歡迎先點這邊回顧唷!


新增得分文字

我們用程式碼新增顯示遊戲總分的文字,放在遊戲畫面的最上方

新增一個外層的節點 (SKSpriteNode)

  • 命名為 scoreNode,給它一個灰底顏色,寬度與螢幕同寬,高 30
  • 設定 anchorPointCGPoint(x: 0, y: 0.5)
  • scoreNode 加到遊戲場景裡

新增一個文字節點 (SKLabelNode)

  • 命名為 labelScore,讓他顯示的文字為 Score: \(score),將標題與分數組合起來顯示
  • fontColor:設定文字顏色
  • fontSize:設定文字大小
  • fontName:設定字體
  • position:設定位置
  • horizontalAlignmentMode:設定水平對齊方式
  • verticalAlignmentMode:設定垂直對齊方式
  • labelScore 加到 scoreNode

新增一個計分的變數

  • 命名為 score

調整位置

applySafeArea 方法裡調整位置:

  • mapNode:位置再往下移一個 scoreNode 的高
  • scoreNode:位置往下移 topSafeArea 跟自身一半的高 (因 anchorPoint y 為 0.5)
  • GameScene.swift
class GameScene: SKScene {
    ...
    var scoreNode: SKSpriteNode?
    var labelScore: SKLabelNode?
    var score: Int = 0
    
    override func didMove(to view: SKView) {
        ...
        self.scoreNode = SKSpriteNode(color: .darkGray, size: CGSize(width: CGFloat(self.size.width), height: CGFloat(30)))
        self.labelScore = SKLabelNode(text: "Score: \(score)")
        if let scoreNode = self.scoreNode, let labelScore = self.labelScore {
            scoreNode.anchorPoint = CGPoint(x: 0, y: 0.5)
            self.addChild(scoreNode)

            labelScore.fontColor = UIColor.white
            labelScore.fontSize = CGFloat(24)
            labelScore.fontName = "Copperplate"
            labelScore.position = CGPoint(x: 10, y: 0)
            labelScore.horizontalAlignmentMode = .left
            labelScore.verticalAlignmentMode = .center
            scoreNode.addChild(labelScore)
        }
    }
    
    func applySafeArea() {
        ...
//        if let mapNode = self.mapNode {
//            mapNode.position = CGPoint(x: 0, y: -self.topSafeArea)
//        }
        if let mapNode = self.mapNode, let scoreNode = self.scoreNode {
            mapNode.position = CGPoint(x: 0, y: -self.topSafeArea - scoreNode.size.height)
            scoreNode.position =  CGPoint(x: 0 ,y: -self.topSafeArea - scoreNode.size.height/2)
        }
    }
}

執行結果

https://imgur.com/yHMIfN0.gif


加上分數

先新增一個加分的方法 addScore(add: Int),改變 score 變數的值,也改變 labelScore 顯示的文字

  • GameScene.swift
class GameScene: SKScene {
    ...
    func addScore(add: Int) {
        self.score += add
        self.labelScore?.text = "Score: \(self.score)"
    }
}

水晶

主角與水晶碰觸時,加上水晶得分:10

  • GameScene.swift
class GameScene: SKScene {
    ...
    override func update(_ currentTime: TimeInterval) {
        for crystal in self.crystals where !crystal.isGotten && crystal.gridX == sam.gridX && crystal.gridY == sam.gridY {
            ...
            self.addScore(add: 10)
        }
    }
}

魔幻水晶

主角與魔幻水晶碰觸時,加上魔幻水晶得分:100

class GameScene: SKScene {
    ...
    override func update(_ currentTime: TimeInterval) {
        for magicCrystal in self.magicCrystals where !magicCrystal.isGotten && magicCrystal.gridX == sam.gridX && magicCrystal.gridY == sam.gridY {
            ...
            self.addScore(add: 100)
        }
    }
}

香菇

主角與香菇碰觸時,加上香菇得分:200

class GameScene: SKScene {
    ...
    override func update(_ currentTime: TimeInterval) {
        for mushroom in self.mushrooms where !mushroom.isGotten && mushroom.gridX == sam.gridX && mushroom.gridY == sam.gridY {
            ...
            self.addScore(add: 200)
        }
    }
}

擊退怪物

主角與怪物碰觸,且怪物模式為逃逸時,加上擊退得分:50

class GameScene: SKScene {
    ...
    override func update(_ currentTime: TimeInterval) {
        for weather in self.weathers where (weather.gridX == sam.gridX && abs(weather.node.position.y - sam.node.position.y) <= CGFloat(self.gridWH + 6) || weather.gridY == sam.gridY && abs(weather.node.position.x - sam.node.position.x) <= CGFloat(self.gridWH + 6)) && (gridMapping.purpleTree.x != sam.gridX && gridMapping.purpleTree.y != sam.gridY)
        {
            if weather.mode == .ATTACK || weather.mode == .PLAY {
                ...
            } else if weather.mode == .ESCAPE {
                ...
                self.addScore(add: 50)
            }
        }
    }
}

執行結果

成功將分數累積在畫面上方囉!
https://imgur.com/dey7rz5.gif

今日小結

目前我們已經可以計算得分囉~但是...
累積的得分在關閉遊戲後,就會重置了,辛苦得來的分數就這樣飛了 /images/emoticon/emoticon02.gif
還缺少將最高得分紀錄起來的功能!
遊戲要能破紀錄,才會更有挑戰性~
明日會教大家如何將最高得分紀錄在本機裡。


上一篇
從零開始的8-bit迷宮探險【Level 22】奧義隱身術 & 時間靜止術
下一篇
從零開始的8-bit迷宮探險【Level 24】誰才是高玩?紀錄本機最高得分
系列文
從零開始的8-bit迷宮探險!Swift SpriteKit 遊戲開發實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言