从零开始的8-bit迷宫探险【Level 20】搜集水晶可以召唤神龙吗?

不知道跑了多久,可能有一世纪的感觉,山姆终於累得停了下来。
上帝关起了一道门,总会为你开启另一扇窗。
一片蓝色、发光的物体印入眼帘。
「难道这就是传说中的水晶!」山姆兴奋地拿起这个得来不易的珍宝。

今日目标

  • 新增收集物类别
  • 在迷宫中加入水晶
  • 让主角可以收集水晶,碰触後水晶消失

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


新增收集物类别

我们新增一个共用的收集物类别,可以让水晶、魔幻水晶、香菇共同使用
首先新增一个 swift 档案

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

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

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

引入 SpriteKit

请记得先 import SpriteKit

import SpriteKit

类别内容

记录收集物的属性:

  • node:纪录收集物的 SKSpriteNode 资讯
  • gridX:纪录收集物的格子点 x
  • gridY:纪录收集物的格子点 y
  • isGotten:纪录收集物是否已经被收集

在建构子 (init) 写上初始化时需带入的参数:

  • gridWH:一格的宽度
  • gridX:收集物的格子位置 x
  • gridY:收集物的格子位置 y
  • imageName:收集物的图片

在建构子中,储存带入的参数值,并新增一个 SKSpriteNodeimageNamed 带入图片名称,并将定位点 (anchorPoint)、尺寸 (size)、位置 (position)、层级 (zPosition) 都设定好。

新增 setGotten 方法

  • 让外部能设定 isGotten 的值
  • 判断 isGotten 值,如果被收集了,就将 node 的 zPosition 设定为 ZPosition.HIDE。反之则将 zPosition 设定为 ZPosition.COLLECTION
class Collection {
    var node: SKSpriteNode
    var gridX: Int = 0
    var gridY: Int = 0
    var isGotten: Bool = false
    
    init(gridWH: Int, gridX: Int, gridY: Int, imageName: String) {
        self.gridX = gridX
        self.gridY = gridY
        
        self.node = SKSpriteNode(imageNamed: imageName)
        self.node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        self.node.size.width = CGFloat(gridWH)
        self.node.size.height = CGFloat(gridWH)
        self.node.position = CGPoint(x: gridWH * gridX + (gridWH/2), y: -gridWH * gridY - (gridWH/2))
        self.node.zPosition = CGFloat(ZPosition.COLLECTION)
    }
    
    func setGotten(isGotten: Bool) {
        self.isGotten = isGotten
        if isGotten {
            self.node.zPosition = CGFloat(ZPosition.HIDE)
            return
        }
        self.node.zPosition = CGFloat(ZPosition.COLLECTION)
    }
}

在迷宫中加上水晶

地图阵列加上水晶

在先前的章节已经设定过我们地图上要画的图片代号,想复习的朋友可以点这边

  • 我们使用 . 代号代表这个位置要画上水晶
  • GameScene.swift
let mapDraw = [
    "ccccccccpccccccci",
    "   .....e*......b",
    "aam.1ji.s.11.zy.b",
    "  d.3gh....1.wx.b",
    "jcl.....ji.1....b",
    "d*...11.gh...rt.b",
    "d.11.nm....2....b",
    "d..1.kl.22.1.naah",
    "ot...       .b   ",
    "d..1.jcu vci.b   ",
    "d.12.d     b.kccc",
    "d+...gaaaaah.    ",
    "gaam.       .11.n",
    "   d.rt.1#.q....b",
    "   d....21.e.ji.b",
    "cccl.ji....e.gh.b",
    "    .gh.13.s....b",
    "aaam....1....21.b",
    "   d...23.rt.1..b",
    "   d.1.........3b",
    "jccl.1.rft.3.1.1b",
    "d*.............*b",
    "gaaaaaaaaaaaaaaah",
]

准备水晶图片

请准备好图片,并且拖拉进专案中

https://imgur.com/J0cxMBk.png

加上水晶

  • 先宣告水晶阵列的变数 crystals,准备将所有画面上的水晶存在这边
  • 在先前的 drawMap 方法里,再加上 "." 的 case
  • 新增收集物类别 Collection 的实体,将需要的参数带入
  • mapNode 里加入收集物的 node
  • 将水晶的实体存在 crystals 阵列中
  • GameScene.swift
class GameScene: SKScene {
    ...
    var crystals: [Collection] = []
    ...
    func drawMap() {
        for i in 0..<gridYCount {
            let mapRowArr = Array(mapDraw[i]);
            for j in 0..<gridXCount {
                let mapKeys = wallMapping.keys
                switch mapRowArr[j] {
                ...
                case ".":
                    let crystal = Collection(gridWH: self.gridWH, gridX: j, gridY: i, imageName: "crystal")
                    self.mapNode!.addChild(crystal.node);
                    self.crystals.append(crystal)
                default:
                    break
                }
            }
        }
    } 
}

执行结果

https://imgur.com/j1XPcCO.gif

水晶成功出现啦!
角色的层级也正常的显示在水晶上方。
接着再加上主角经过时,水晶消失的效果,就ok了!


主角与水晶碰触後,水晶消失

  • update 方法里,再加上主角跟水晶之间的位置判断,当主角跟水晶的格子位置一样时,并且还没有被收集时,就将水晶设定成被收集了 setGotten(isGotten: true)
  • 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 {
            crystal.setGotten(isGotten: true)
        }
    }
}

执行结果

https://imgur.com/N3kOpwy.gif

成功出现水晶被收集的效果了!


今日小结

有了收集物类别,明日来继续新增另一个魔幻水晶的类别吧!/images/emoticon/emoticon07.gif


<<:  第二十三天:在 TeamCity 上产生覆盖率报告

>>:  【Day 13】 浅谈 OSM

DAY 3- Enigma

纳粹德国的超强机器,唯有机器才能破解机器。 今天来介绍二战时期被纳粹大规模使用的加密机器 - Eni...

Day 26 一直线的前进_____ 不能断啊!

我们不能总在弹性限度里活动,要爆发,要超越,才会有质的提高。 《iT邦帮忙铁人赛的观点》(以下简称铁...

ISO 27001 资讯安全管理系统 【解析】(三)

参、管理系统概述 品质管理系统应该是所有管理系统的基础,ISO/TC 176在制订品质管理系统的标准...

Day38 ( 游戏设计 ) 狙击气球 ( 两倍变焦 )

狙击气球 ( 两倍变焦 ) 教学原文参考:狙击气球 ( 两倍变焦 ) 这篇文章会延伸「 狙击望远镜 ...

Day-06 说明类别(class)跟模组(module)的差别?

在 Ruby 里,有类别 (class) 和模组 (module) ,但其实两者差别并不大哦! 他...