「呀!呀!」一只乌鸦飞了过去,因为视线不明,让移动的黑影更加引人遐想。
在这诺大的森林里,就只有山姆一个人,登山杖插进土里的声音清楚回荡在空气中。
山姆调整了一下背包,深深吸了一口气,再次提起脚步前进。
PS. 这里是开发 iOS 手机游戏的系列文,如果还没看过之前
剧情文章的朋友,欢迎先点这边回顾唷!
我们新增一个共用的角色类别,可以让主角继承,未来也能让怪物继承。
首先新增一个 swift 档案,将程序码区开,比较方便管理。
首先点选新增档案
选择 Swift File -> Next
将档案命名为 GameCharacter,点击 Create 按钮,完成 .swift 档的新增
记得万事先 import
import SpriteKit
先建立一个列举,加入 NONE
及主角山姆 SAM
enum Role: String {
case NONE = "none"
case SAM = "sam"
}
我们希望能记录角色的一些属性:
我们在建构子 (init) 写上初始化时需带入的参数:
在建构子中,储存带入的参数值,并且新增一个 SKSpriteNode
,将定位点 (anchorPoint)、尺寸 (size)、位置 (position)、层级 (zPosition) 都设定好。
class GameCharacter {
var role: Role = .NONE
var node: SKSpriteNode
var gridWH: Int
var gridX: Int
var gridY: Int
var startGridX: Int
var startGridY: Int
var imageName: String
init(gridWH: Int, startGridX: Int, startGridY: Int, imageName: String, zPosition: CGFloat, role: Role) {
self.role = role
self.gridWH = gridWH
self.gridX = startGridX
self.gridY = startGridY
self.startGridX = startGridX
self.startGridY = startGridY
self.imageName = imageName
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 * startGridX + (gridWH/2), y: -gridWH * startGridY - (gridWH/2))
self.node.zPosition = zPosition
}
}
我们的游戏画面就像是个画布层层堆叠,放在上面的物体都是有层级的,数字越高的在越上方
而 SpriteKit 会帮我们预设定为:0.0
先试想游戏会出现几种交叠在一起的物体:收集品、主角、坏天气怪物、能隐身的树,分别帮他们先定义好正确的层级。其中一种是隐藏 (-1),当设定为此种类型,则会有消失在画面中的效果。
请先定义好 ZPosition
enum ZPosition {
static let HIDE = -1
static let COLLECTION = 1
static let SAM = 2
static let WEATHER = 3
static let PURPLE_TREE = 4
}
新增一个主角类别档案:Sam.swift,继承 GameCharacter
类别。
imageName 带入主角的图档名称 sam
zPosition 带入 ZPosition.SAM
role 带入 .SAM
(因为父类别已经有定义 role 的型态为 Role,所以可将 Role.SAM 省略为 .SAM)
import SpriteKit
class Sam: GameCharacter {
init(gridWH: Int, startGridX: Int, startGridY: Int) {
super.init(gridWH: gridWH, startGridX: startGridX, startGridY: startGridY, imageName: "sam", zPosition: CGFloat(ZPosition.SAM), role: .SAM)
}
}
考虑到未来会有不同种类的角色,分别会有不同的起始点 (这边提的起始点是指位於迷宫格子中的位置),可以先新增一个结构 (struct),定义不同种类位置的 (x, y) 常数值,方便未来管理。请先新增一个 samStart
的 x 及 y 值。
struct gridMapping {
struct samStart {
static let x = 1
static let y = 1
}
}
在 didMove 中,创建一个 Sam 类别的实体,并将起始位置带入。
接着将实体的 node 添加到 mapNode 中。
class GameScene: SKScene {
...
var sam: Sam?
override func didMove(to view: SKView) {
...
self.sam = Sam(gridWH: self.gridWH, startGridX: gridMapping.samStart.x, startGridY: gridMapping.samStart.y)
self.mapNode!.addChild(self.sam!.node)
}
}
主角出现在画面中了
如果只有一张贴图,游戏会比较不生动,加入动画可以提升精致度。
我们试着制作两张主角手部举起登山杖的连续图,面朝下的方向,分别取名为:
回到角色类别,找到设定图片的地方,将原本建立 SKSpriteNode 的地方做调整。
SKTexture
新增两张序列图SKAction.animate
建立图片序列动画,timePerFrame
代表每张图片的持续时间(秒)SKAction.repeatForever
,带入原本的图片序列动画,让它重复播放.run
,让它播放动画// self.node = SKSpriteNode(imageNamed: imageName)
let sequence1 = SKTexture(imageNamed: imageName + "_1")
let sequence2 = SKTexture(imageNamed: imageName + "_2")
let ani = SKAction.animate(with: [sequence1, sequence2], timePerFrame: 0.4)
let aniRepeat = SKAction.repeatForever(ani)
self.node = SKSpriteNode(texture: sequence1)
self.node.run(aniRepeat, withKey: "sequence")
将图档名称改为 sam_down
super.init(gridWH: gridWH, startGridX: startGridX, startGridY: startGridY, imageName: "sam_down", zPosition: CGFloat(ZPosition.SAM), role: .SAM)
执行後就可以看到主角有动画了!
我们发现主角在地图中看起来似乎有点小,想要将角色图片调整大一点。
因为角色的 anchorPoint 是定在 (0.5, 0.5),因此我们可以直接将 node 的 size 调大,不会影响到定位。
将宽高各加上 13 微调
self.node.size.width = CGFloat(gridWH + 13)
self.node.size.height = CGFloat(gridWH + 13)
主角在画面上能显示序列动画罗!
明日来控制主角移动吧!
<<: IT 铁人赛 k8s 入门30天 -- day7 K8s YAML 设定档
>>: DAY06 - API串接常见问题 - CORS - 解决CORS问题篇
「子非鱼,安知鱼之乐。」 在介绍协定之前, 我们要来介绍一个非常重要的概念,叫做凭证颁发机构(Cer...
前言 当子元素溢出母元素时该如何处理 可单指设定X轴或Y轴 overflow-x overflow-...
昨天我们提到红色框框里面的东西,今天就来根据他们的作用进行简单介绍吧! AppDelegate.sw...
当我在Unreal Engine 4.27.0下载好试图启动软件时,跳出了下面这个视窗, U...