从零开始的8-bit迷宫探险【Level 26】这游戏没有华佗,不能补血啊!Game Over 场景切换

一直遭到攻击的山姆,生命值也快用尽了。
「快离开我们的地盘!」山姆被 Rain 跟 Storm 团团包围着。
「这迷宫的出口,不知道长什麽样子呢?」

今日目标

  • 切换至游戏结束场景
  • 显示本次游戏得分及历史最高得分
  • 加上破纪录提示
  • 加上重新开始按钮,可以切换至游戏场景并重新开始游戏

PS. 这里是开发 iOS 手机游戏的系列文,如果还没看过之前 剧情 文章的朋友,欢迎先点这边回顾唷!


建立游戏结束场景

首先,我们先新增新的场景,包含 .sks 及 .swift,并且将对应的类别名称填入 .sks 档案中

新增游戏结束场景

  • 点选新增档案
    https://imgur.com/DyRgPfA.png

  • 选择 SpriteKit Scene -> Next
    https://imgur.com/quZHr3g.png

  • 将档案命名为 GameOverScene,点击 Create 按钮,完成 .sks 档的新增

新增游戏结束类别

  • 点选新增档案
    https://imgur.com/DyRgPfA.png

  • 选择 Swift File -> Next
    https://imgur.com/IJukGWI.png

  • 将档案命名为 GameOverScene,点击 Create 按钮,完成 .swift 档的新增

  • 将 GameOverScene.sks 的 Custom Class 填上 GameOverScene
    https://imgur.com/NnG0FAl.png

游戏结束类别内容

  • 引入 SpriteKit
  • 新增两个分数变数 scorebestScore,用来记录游戏得分及最高得分
  • 新增重新开始按钮,包含背景图片及文字,使用 SKSpriteNode 及 SKLabelNode 组合而成
  • 设定背景颜色为 .black
  • 加上游戏结束的标题 labelTitle,显示 Game Over!
  • 加上游戏得分及最高得分的文字节点 labelScorelabelBest
  • 加上重新开始按钮 restartNodelabelRestart
  • GameOverScene.swift
import SpriteKit

class GameOverScene: SKScene {
    var score: Int = 0
    var bestScore: Int = 0
    var restartNode = SKSpriteNode(imageNamed: "button")
    var labelRestart = SKLabelNode(text: "RESTART")
    
    override func didMove(to view: SKView) {
        self.backgroundColor = .black
        
        let labelTitle = SKLabelNode(text: "Game Over!")
        labelTitle.fontColor = UIColor(red: 39/255, green: 90/255, blue: 129/255, alpha: 1)
        labelTitle.fontSize = CGFloat(50)
        labelTitle.fontName = "Copperplate"
        labelTitle.position = CGPoint(x: 0, y: 200)
        labelTitle.horizontalAlignmentMode = .center
        labelTitle.verticalAlignmentMode = .center
        self.addChild(labelTitle)
        
        let labelScore = SKLabelNode(text: "Your Score: \(self.score)")
        labelScore.fontColor = UIColor.white
        labelScore.fontSize = CGFloat(24)
        labelScore.fontName = "Copperplate"
        labelScore.position = CGPoint(x: 0, y: 100)
        labelScore.horizontalAlignmentMode = .center
        labelScore.verticalAlignmentMode = .center
        self.addChild(labelScore)
        
        let labelBest = SKLabelNode(text: "Best Score: \(self.bestScore)")
        labelBest.fontColor = UIColor.white
        labelBest.fontSize = CGFloat(24)
        labelBest.fontName = "Copperplate"
        labelBest.position = CGPoint(x: 0, y: 60)
        labelBest.horizontalAlignmentMode = .center
        labelBest.verticalAlignmentMode = .center
        self.addChild(labelBest)
        
        self.restartNode.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        self.restartNode.size.width = CGFloat(208)
        self.restartNode.size.height = CGFloat(74)
        self.restartNode.position = CGPoint(x: 0, y: -100)
        self.addChild(self.restartNode)
        
        self.labelRestart.fontColor = UIColor(red: 39/255, green: 90/255, blue: 129/255, alpha: 1)
        self.labelRestart.fontSize = CGFloat(30)
        self.labelRestart.fontName = "Copperplate"
        self.labelRestart.position = CGPoint(x: 0, y: 2)
        self.labelRestart.verticalAlignmentMode = .center
        self.restartNode.addChild(self.labelRestart)
    }
}

切换至场景

  • 调整 gameStop 方法
    • 将储存最高分的程序码移动到 gameOver()
    • 在生命值小於 0 时,启动一个 Timer,3 秒後执行 gameOver()
  • gameOver
    • 游戏结束时,将最高分储存到本机中
    • 新增一个 GameOverScene 实体,将 self.scoreself.bestScore 的值写入
    • 使用 SKTransition,让游戏场景与游戏结束场景中间有个转场动画特效。特效的选择有很多,大家可以带入自己喜欢的特效,这边使用 SKTransition.doorway
    • 带入特效并切换至 GameOverScene 场景
  • GameScene.swift
class GameScene: SKScene {
    ...
    func gameStop() {
        ...
//        let setting = Setting(bestScore: self.bestScore)
//        self.setBestScore(setting: setting)

        self.samLife -= 1
        if self.samLife < 0 {
            // 游戏结束场景
            Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(gameOver), userInfo: nil, repeats: false)
        } else {
            // 重新开始
            Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(gameReset), userInfo: nil, repeats: false)
        }
    }
    @objc func gameOver() {
        // 储存最高分
        let setting = Setting(bestScore: self.bestScore)
        self.setBestScore(setting: setting)
        
        // 切换场景
        if let endScene = GameOverScene(fileNamed: "GameOverScene") {
            endScene.score = self.score
            endScene.bestScore = self.bestScore
            let transition = SKTransition.doorway(withDuration: 1)
            self.view?.presentScene(endScene, transition: transition)
        }
    }
}

执行结果

成功切换至游戏结束场景罗!而且也显示了得分纪录
https://imgur.com/adCI27n.gif


破纪录文字

我们再加上破纪录的提示文字,让场景更丰富。判断当本次游戏得分大於或等於最高得分,且不为 0 时,就显示破纪录文字。这边使用之前用过的 SKAction.fadeAlpha 来制作让文字闪烁的感觉

  • GameOverScene.swift
class GameOverScene: SKScene {
    override func didMove(to view: SKView) {
        ...
        if self.score >= self.bestScore && self.score != 0 {
            let labelBreak = SKLabelNode(text: "Break the record!!")
            labelBreak.fontColor = UIColor.white
            labelBreak.fontSize = CGFloat(32)
            labelBreak.position = CGPoint(x: 0, y: 0)
            let ani1 = SKAction.fadeAlpha(to: 0, duration: 0.6)
            let ani2 = SKAction.fadeAlpha(to: 1, duration: 0.3)
            let aniAlpha = SKAction.sequence([ani1, ani2])
            let aniRepeat = SKAction.repeatForever(aniAlpha)
            labelBreak.run(aniRepeat)
            self.addChild(labelBreak)
        }
    }
}

执行结果

画面中出现闪亮亮的破纪录了!/images/emoticon/emoticon74.gif
https://imgur.com/yLsROFv.gif


重新开始

最後,让重新开始按钮,可以被点击吧!
跟之前用过的方式一样,覆写 touchesBegan 方法,判断当触碰的位置是 self.restartNodeself.labelRestart 时,切换回去 GameScene 场景,并且加上 SKTransition.fade 的转场效果,最後呼叫 applySafeArea 方法,校正画面。

  • GameOverScene.swift
class GameOverScene: SKScene {
    ...
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in (touches) {
            let location = touch.location(in: self)
            if self.atPoint(location) == self.restartNode || self.atPoint(location) == self.labelRestart {
                if let gameScene = GameScene(fileNamed: "GameScene") {
                    let transition = SKTransition.fade(withDuration: 1)
                    self.view?.presentScene(gameScene, transition: transition)
                    gameScene.applySafeArea()
                }
            }
        }
    }
}

执行结果

按下重新开始游戏按钮後,回到游戏场景,可以看到生命值重新回到 3,右上角也有之前的最高得分
https://imgur.com/hjcFHht.gif


参考来源:
SKTransition
fadeAlpha(to:duration:)


<<:  Android学习笔记25

>>:  【Day 19】Google Apps Script - API 篇 - Spreadsheet Service - 电子试算表服务范例-新增内容

< 关於 React: 开始打地基| 建立一个最小的单位 “Element” >

09-04-2021 避免与component混淆的最小单位 在建立element时,与DOM el...

[想试试看JavaScript ] 资料型态 与字串

年初我开始学程序的时候,就是去网路上随意翻阅文章就开始学了。 很常会被一堆专有名词吓傻。即使努力默记...

[Day13] 补充说明 – csrf

今天要来补充一下Day9 – views有说明到的csrf,虽然这些东西某某百科都有,那我会特别补充...

初探编码的世界,Ruby 30 天刷题修行篇第六话

大家好,我是 A Fei,今天是连假最後一天,虽然正在忙转职根本没有放假的感觉,但看到手机里亲友们一...

基本元件

在使用基本元件时,使用的观念与时下常见的IDE工具相类似。我们由布局开始构思,如果有需要多页面,则需...