正当山姆思考结界问题的同时,啪嗒!啪嗒!雨落了下来。
「下雨了!」山姆赶紧找寻遮蔽物,跑到了一棵大树下。
「呼,好险。」山姆喘了一口气,还好背包没有湿掉。
山姆蹲下系紧因奔跑而松脱的鞋带,抬起头时,出现了一双眼睛紧盯着。
四目交对之下,山姆快速扫遍脑中的资料库...
「那是...雪人?这个季节里居然有雪人!?」
PS. 这里是开发 iOS 手机游戏的系列文,如果还没看过之前
剧情文章的朋友,欢迎先点这边回顾唷!
依照我们的游戏设计规划,怪物共有四种:
以下先设计好怪物的样子,每种怪物都先分别设计两张动画序列图,我们先制作一种方向 (往下走的正面),并将图片拖移进专案中
下雨 (Rain):
暴风雨 (Storm):
闪电 (Lightning):
雪人 (Snow):
先前已经定义过主角的一些设定值,我们先将怪物的设定值也加进专案中
在之前主角篇新增的 Role
列举,再多加入四种怪物名称 RAIN
、STORM
、LIGHTNING
、SNOW
enum Role: String {
case NONE = "none"
case SAM = "sam"
case RAIN = "rain"
case STORM = "storm"
case LIGHTNING = "lightning"
case SNOW = "snow"
}
将怪物在迷宫中的起始位置定义在之前宣告的 gridMapping
结构 (struct) 中,方便一起管理
struct gridMapping {
...
struct rainStart {
static let x = 7
static let y = 8
}
struct stormStart {
static let x = 8
static let y = 10
}
struct lightningStart {
static let x = 6
static let y = 10
}
struct snowStart {
static let x = 9
static let y = 8
}
}
接着,请新增一个 swift 档案,命名为 Weather.swift
点选新增档案
选择 Swift File -> Next
将档案命名为 Weather,点击 Create 按钮,完成 .swift 档的新增
请先 import SpriteKit
import SpriteKit
在这边我们先定义好怪物将会进行的移动模式种类,将会在未来的章节实做移动的方式
enum Mode {
case ATTACK
case ESCAPE
case PLAY
case REBIRTH
}
将怪物类别 (Weather) 继承角色类别 (GameCharacter)
接着加上怪物专有的一些属性:
.ATTACK
true
接着在建构子 (init) 写上初始化时需带入的参数:
在 super.init 的时候带入的参数:
"\(role.rawValue)_down"
,对应到前面加入的图片档名,例如 rain_down。在 GameCharacter 类别中,先前已经在 init 写好播放动画序列图的程序码,带入图档名就可以产生序列动画了ZPosition.WEATHER
,在先前的章节已经加好的怪物层级并且将 sam
主角的资料存起来
class Weather: GameCharacter {
var mode: Mode = .ATTACK
var isTrace: Bool = true
var targetGridX = 0
var targetGridY = 0
var sam: Sam?
init(gridWH: Int, startGridX: Int, startGridY: Int, role: Role, sam: Sam) {
super.init(gridWH: gridWH, startGridX: startGridX, startGridY: startGridY, imageName: "\(role.rawValue)_down", zPosition: CGFloat(ZPosition.WEATHER), role: role)
self.sam = sam
}
}
回到 GameScene,我们新增怪物的实体,将怪物新增到游戏中
weathers
,准备储存所有的怪物didMove
里分别新增四个怪物:rain
、storm
、lightning
、snow
,并将它们的 node
加到 mapNode
里面,以及将实体加进 weathers
阵列中class GameScene: SKScene {
...
var weathers: [Weather] = []
override func didMove(to view: SKView) {
...
let rain = Weather(gridWH: self.gridWH, startGridX: gridMapping.rainStart.x, startGridY: gridMapping.rainStart.y, role: .RAIN, sam: self.sam!)
self.mapNode!.addChild(rain.node)
self.weathers.append(rain)
let storm = Weather(gridWH: self.gridWH, startGridX: gridMapping.snowStart.x, startGridY: gridMapping.snowStart.y, role: .SNOW, sam: self.sam!)
self.mapNode!.addChild(storm.node)
self.weathers.append(storm)
let lightning = Weather(gridWH: self.gridWH, startGridX: gridMapping.lightningStart.x, startGridY: gridMapping.lightningStart.y, role: .LIGHTNING, sam: self.sam!)
self.mapNode!.addChild(lightning.node)
self.weathers.append(lightning)
let snow = Weather(gridWH: self.gridWH, startGridX: gridMapping.stormStart.x, startGridY: gridMapping.stormStart.y, role: .STORM, sam: self.sam!)
self.mapNode!.addChild(snow.node)
self.weathers.append(snow)
}
}
来看一下执行的成果吧!
目前我们有主角
(Sam) 及怪物
(Weather) 两种类别了,同样都继承角色
(GameCharacter) 父类别,而透过继承类别的好处是省略了一些重复的程序码,像是初始化的地方,已经可以不用再多写一次播放序列动画的程序码,并且也能依照特殊需求,再多加入特别的参数,使我们能更快速建立不同种类的角色。
聪明的各位应该也猜到了,接下来一样可以遵循前面建立好的移动协定 Move
,明日就来带着大家一起实作让怪物动起来吧!
>>: [Day23] NLP会用到的模型(六)-transformer架构
由於JavaScript是单线程的语言,所以从上而下设计就很重要,若有点困难可以先去看Functio...
D3js 动画事件小技巧 用途 在d3世界中,如果想使用起来不是透过事件驱动或是外部驱动,而是想要产...
别再用 setTimeOut、setInterval 写动画啦! 如果你有用 js 写过动画,那通...
今天要来看的是JavaScript RegExp 对象,因为刚好最近做表单要用到,因此就来顺便做点笔...
שלום,我是Charlie! 在Day10当中我们完成了後端的商品资料API,在今天我们将完成前端...