本次項(xiàng)目實(shí)戰(zhàn)所用的資源均來自保衛(wèi)蘿卜官方App 保衛(wèi)蘿卜官網(wǎng)
保護(hù)知識(shí)產(chǎn)權(quán),人人有責(zé)结澄!
前言:從事iOS應(yīng)用開發(fā)好幾年了拄查,跟著Swift語言的發(fā)展過來的,這些年來沒有接觸過游戲開發(fā)煤墙,感覺挺可惜的麻惶,所以決定開始學(xué)習(xí)用SpriteKit來開發(fā)游戲馍刮。寫文章把自己的開發(fā)過程記錄下來,希望能夠和其他開發(fā)者更多進(jìn)行交流學(xué)習(xí)窃蹋。
創(chuàng)建項(xiàng)目
開發(fā)環(huán)境:Xcode12卡啰、Swift 5
我們在Xcode上選擇File → New → Project
或者使用快捷鍵Shift + Command + N
來打開創(chuàng)建項(xiàng)目面板静稻,填入項(xiàng)目名稱和組織名稱,游戲語言Swift
匈辱,游戲框架選擇SpriteKit
振湾,點(diǎn)擊Next
開始自己的新項(xiàng)目。
項(xiàng)目配置
新項(xiàng)目中有些文件我們暫時(shí)用不到亡脸,先把GameScene.sks
和Actions.sks
這兩個(gè)文件刪除了吧押搪,這兩個(gè)文件是為了方便管理SKNode(節(jié)點(diǎn))
和SKAction(動(dòng)作)
的。我們先從代碼開始學(xué)習(xí)暫時(shí)就不需要這種方式來構(gòu)建場景浅碾。
然后我們創(chuàng)建三個(gè)新的目錄Utils
大州、Nodes
和Scenes
,分別用來管理通用垂谢、節(jié)點(diǎn)和場景類的文件摧茴。我們在Utils
目錄下創(chuàng)建Functions.swift
、Constants.swift
和Extensions.swift
三個(gè)文件埂陆,接著在Nodes
目錄下創(chuàng)建BaseNode.swift
文件,然后把GameScene.swift
文件移動(dòng)到Scenes
目錄下娃豹,最后項(xiàng)目的文件結(jié)構(gòu)如下:
AppDelegate.swift // 應(yīng)用入口
GameViewController.swift // 視圖控制器
Main.storyboard // 故事板
|-- Utils // 通用目錄
|-- Constants.swift // 通用常量
|-- Extensions.swift // 通用拓展
|-- Functions.swift // 通用方法
|-- Nodes // 節(jié)點(diǎn)目錄
|-- BaseNode.swift // 自定義的 SKSpriteNode 節(jié)點(diǎn)
|-- Scenes // 場景目錄
|-- GameScene.swift // 應(yīng)用主場景
添加資源
正所謂兵馬未動(dòng)糧草先行焚虱,項(xiàng)目要開發(fā)了當(dāng)然要準(zhǔn)備圖片和音頻等資源啦,把資源文件添加進(jìn)項(xiàng)目里面吧懂版,注意勾選Copy items if needed
鹃栽,選擇Create groups
,然后點(diǎn)擊Add
躯畴,這些資源包括了應(yīng)用圖標(biāo)民鼓、啟動(dòng)圖、散圖蓬抄、紋理集丰嘉、音頻、數(shù)值設(shè)定等文件嚷缭。
設(shè)置應(yīng)用圖標(biāo)和啟動(dòng)圖
使用快捷鍵 Command + R
開始編譯項(xiàng)目
開始的項(xiàng)目沒有應(yīng)用圖標(biāo)饮亏、啟動(dòng)圖,我們需要自己設(shè)置阅爽。把資源文件里的應(yīng)用圖標(biāo)對應(yīng)地拖進(jìn)項(xiàng)目吧路幸,然后給應(yīng)用起一個(gè)新的名稱
因?yàn)橛螒蝽?xiàng)目基本是橫屏的,所以需要修改項(xiàng)目支持的屏幕方向付翁,在項(xiàng)目設(shè)置中的Device Orientation
把 Portrait
勾選項(xiàng)給取消掉简肴。
應(yīng)用啟動(dòng)頁推薦使用 LaunchScreen.storyboard
, 創(chuàng)建一個(gè) LaunchScreen
文件,然后在該文件上添加自己想要的啟動(dòng)頁視圖就好了百侧,這里我直接放了一張圖片砰识,只需要一張橫屏圖就可以適配絕大部分機(jī)型了能扒。
配置場景
創(chuàng)建場景
新項(xiàng)目的的文件入口是 Main.storyboard → GameViewController.swift → GameScene.swift
因?yàn)槲覀儎h除了默認(rèn)生成的場景文件GameScene.sks
,里面的場景也無法獲取了仍翰,我們需要通過代碼來創(chuàng)建新的場景赫粥,我們需要在GameViewController.swift
文件的viewDidLoad()
方法中修改成以下代碼:
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
let scene = GameScene(size: CGSize(width: 1334, height: 750))
// 設(shè)置錨點(diǎn)位置在中心
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
// 設(shè)置場景的縮放模式
scene.scaleMode = .aspectFill
// 展示場景
view.presentScene(scene)
// 設(shè)置忽略同一z軸上的節(jié)點(diǎn)添加順序
view.ignoresSiblingOrder = true
// 顯示fps
view.showsFPS = true
// 顯示節(jié)點(diǎn)數(shù)量
view.showsNodeCount = true
}
}
關(guān)于anchorPoint
的部分我們下面會(huì)進(jìn)行補(bǔ)充,我們接著進(jìn)入 GameScene.swift
文件中予借,刪除系統(tǒng)自動(dòng)生成的代碼越平,剩下的代碼如下:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
override func sceneDidLoad() {
}
}
接下來我們要添加首頁背景圖片,開始之前需要解釋一下紋理集 SKTextureAtlas灵迫,這個(gè)和其他開發(fā)框架中的圖集概念差不多秦叛,比如 cocoa2d-x
中經(jīng)常使用的 .pvr.ccz
文件(支持加密),紋理集或圖集可以把多張圖片集合到一張圖片中瀑粥,用 plist
文件描述每張圖片的尺寸等信息挣跋,可以更方便地管理圖片資源。
項(xiàng)目中的圖片資源我根據(jù) plist
文件編譯生成了對應(yīng)的獲取紋理集圖片的 struct
狞换。
紋理集的目錄結(jié)構(gòu)如下:
|-- Mainscene1-hd.atlasc
|-- Mainscene1-hd.plist
|-- Mainscene1-hd.png
|-- Mainscene1-hd.swift
-
Mainscene1-hd.plist
→ 圖片描述文件 -
Mainscene1-hd.png
→ 合成的大圖片 -
Mainscene1-hd.swift
→ 根據(jù)plist
文件編譯的struct
其中 Mainscene1-hd.swift
的代碼示例如下:
import SpriteKit
struct Mainscene1_hd {
private static let textureAtlas = SKTextureAtlas(named: "Mainscene1-hd")
static let mainbg = textureAtlas.textureNamed("mainbg")
}
添加首頁背景圖片
我們先創(chuàng)建一個(gè)自定義的精靈節(jié)點(diǎn)避咆,方便管理后面添加的所有節(jié)點(diǎn),在?BaseNode.swift
文件中添加下面的代碼:
import SpriteKit
class BaseNode: SKSpriteNode {
init(texture: SKTexture?) {
let size: CGSize = texture != nil ? CGSize(width: texture!.size().width, height: texture!.size().height) : .zero
super.init(texture: texture, color: .clear, size: size)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
來添加首頁的背景圖片吧修噪,在sceneDidLoad()
方法中添加下面的代碼就可以了:
let background = BaseNode(texture: Mainscene1_hd.mainbg)
background.zPosition = -1
addChild(background)
-
sceneDidLoad()
→ 場景加載完成查库,場景初始化后僅會(huì)調(diào)用一次 -
didMove(to view: SKView)
→ 場景入口,每次進(jìn)入場景都會(huì)調(diào)用 -
addChild(_ node: SKNode)
→ 尾部添加子節(jié)點(diǎn)SKNode黄琼,常見的節(jié)點(diǎn)有:
SKSpriteNode → 精靈節(jié)點(diǎn)樊销,最常用的節(jié)點(diǎn),管理紋理實(shí)例(即圖片)
SKVideoNode → 視頻節(jié)點(diǎn)
SKAudioNode → 音頻節(jié)點(diǎn)
SKLabelNode → 文本節(jié)點(diǎn)
SKShapeNode → 形狀節(jié)點(diǎn)
SKEmitterNode → 粒子節(jié)點(diǎn)
SKCropNode → 裁剪節(jié)點(diǎn)
SKEffectNode → 核心圖像過濾節(jié)點(diǎn)脏款,SKScene繼承自該類
SKTileMapNode → 瓦片地圖節(jié)點(diǎn)围苫,常用于構(gòu)建地圖
SK3DNode → 3D節(jié)點(diǎn) -
texture:
SKTexture → 紋理實(shí)例,每個(gè)紋理實(shí)例代表一張可復(fù)用的圖片 -
zPosition = -1
→ 設(shè)置背景圖的圖層在最底層撤师,避免出現(xiàn)同層的圖片被背景遮蓋的情況
運(yùn)行項(xiàng)目剂府,效果如下:
圖片正常顯示出來了,可喜可賀丈氓,鼓掌啪啪啪周循!但是,其實(shí)這里隱藏著一個(gè)問題万俗!因?yàn)榭s放顯示的原因湾笛,場景左右都出現(xiàn)了空白區(qū)域,如果場景中添加的其他節(jié)點(diǎn)超出了背景圖的左右邊界闰歪,就會(huì)顯示成這樣:
這可不符合我們的效果預(yù)期,我都可以想到后面的炮塔子彈超出背景的時(shí)候出現(xiàn)能打穿屏幕的滑稽場面了,我們需要想想辦法了临扮。
裁剪顯示區(qū)域
考慮到項(xiàng)目資源中的背景圖片比例是(960,640)
论矾,再參考如下設(shè)備橫屏寬高比例:
- (4/3 - 1.33) ,設(shè)備:iPad 所有型號(hào)
- (16/9 - 1.77) 杆勇,設(shè)備:iPhone 6/7/8/SE s系列贪壳、Plus系列
- (448/207 - 2.16),設(shè)備:iPhone X/XR/XS/11/12 Max系列蚜退、Pro系列闰靴、mini系列
如果我們使用默認(rèn)的圖片比例1.5
的話,在大部分設(shè)備上都會(huì)出現(xiàn)空白區(qū)域钻注,我用了一個(gè)笨方法蚂且,動(dòng)態(tài)修正場景的尺寸,使其和顯示區(qū)域一致幅恋。
我們在Constants.swift
文件添加以下常量和變量:
public let kImageWidth: CGFloat = 960
public let kImageHeight: CGFloat = 640
public let kImageRatio: CGFloat = kImageWidth/kImageHeight
public var kImageScale: CGFloat = 1.0
然后在Functions.swift
文件添加以下方法:
public func sceneSize() -> CGSize {
var deviceWidth: CGFloat = 0, deviceHeight: CGFloat = 0
// 獲取當(dāng)前設(shè)備的長邊和短邊
let maxBound: CGFloat = max(UIScreen.main.bounds.width, UIScreen.main.bounds.height)
let minBound: CGFloat = min(UIScreen.main.bounds.width, UIScreen.main.bounds.height)
// 判斷當(dāng)前設(shè)備是不是iPhone杏死,如果是,默認(rèn)橫屏顯示
if UIDevice.current.userInterfaceIdiom == .phone {
deviceWidth = maxBound
deviceHeight = minBound
} else {
// 用switch語句判斷當(dāng)前設(shè)備的方向
switch UIDevice.current.orientation {
case .unknown:
// 未知即初次啟動(dòng)未改變屏幕方向捆交,之間設(shè)置當(dāng)前設(shè)備的寬高
deviceWidth = UIScreen.main.bounds.width
deviceHeight = UIScreen.main.bounds.height
case .portrait, .portraitUpsideDown:
// 豎屏
deviceWidth = minBound
deviceHeight = maxBound
default:
// 默認(rèn)橫屏
deviceWidth = maxBound
deviceHeight = minBound
}
}
// 計(jì)算設(shè)備寬高比
let ratio = deviceWidth / deviceHeight
var width: CGFloat = 0, height: CGFloat = 0
// 通過對比設(shè)備的寬高比和圖片的寬高比來確定場景的寬高
if ratio < kImageRatio {
kImageScale = deviceWidth/kImageWidth
width = deviceWidth
height = width / kImageRatio
} else {
kImageScale = deviceHeight/kImageHeight
height = deviceHeight
width = height * kImageRatio
}
return CGSize(width: width, height: height)
}
讓我們回到GameViewController.swift
文件淑翼,修改viewDidLoad()
中的代碼:
override func viewDidLoad() {
super.viewDidLoad()
if let skView = view as? SKView {
let scene = GameScene(size: sceneSize())
scene.backgroundColor = .black
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
scene.scaleMode = .aspectFit
skView.presentScene(scene)
skView.ignoresSiblingOrder = true
skView.showsFPS = true
skView.showsNodeCount = true
}
}
接著還需要在BaseNode.swift
中修改初始化方法:
init(texture: SKTexture?) {
let size: CGSize = texture != nil ? CGSize(width: texture!.size().width * kImageScale, height: texture!.size().height * kImageScale) : .zero
super.init(texture: texture, color: .clear, size: size)
}
運(yùn)行項(xiàng)目,效果如下:
場景的縮放模式
場景有一個(gè)屬性是scaleMode
品追,是一個(gè)枚舉值窒舟,其值如下:
-
aspectFit
此模式可以保持場景比例不變,而且全部顯示在視圖中 -
aspectFill
此模式可以保持場景比例不變诵盼,會(huì)填充整個(gè)視圖,但是可能只有部分場景顯示出來 -
fill
此模式可以讓場景全部顯示出來银还,但是會(huì)導(dǎo)致場景變形 -
resizeFill
此模式可以保證場景與視圖的尺寸相匹配
我們使用的場景拉伸模式是aspectFit
风宁,在iPad等大型顯示設(shè)備上也有不俗的效果,如下所示:
添加節(jié)點(diǎn)和動(dòng)畫
前面我們添加了首頁的背景圖片蛹疯,那么就接著在GameScene
中添加其他節(jié)點(diǎn)吧戒财。
let carrot = SKSpriteNode(texture: Mainscene1_hd.carrot)
addChild(carrot)
效果如下:
場景坐標(biāo)系
仔細(xì)一看,小蘿卜的位置需要調(diào)整稗嘞摇饮寞!此時(shí)我們需要先了解 SKScene
場景中的坐標(biāo)系。
SKScene
場景的坐標(biāo)系默認(rèn)以屏幕的中心點(diǎn)為原點(diǎn)(實(shí)際是SKScene的錨點(diǎn)列吼,可以通過修改值來改變原點(diǎn)位置)
幽崩,分別有x軸、y軸寞钥、z軸慌申。我們添加的子節(jié)點(diǎn)如果沒有進(jìn)行設(shè)置,默認(rèn)都在原點(diǎn)的位置理郑。
那么我們怎么修改節(jié)點(diǎn)的位置呢蹄溉,首先要了解節(jié)點(diǎn)的兩個(gè)屬性 anchorPoint(錨點(diǎn))
和 position(位置)
咨油。
-
anchorPoint(錨點(diǎn))
→ 錨點(diǎn)是一個(gè)節(jié)點(diǎn)的真正核心位置,其概念和現(xiàn)實(shí)中物體的重心差不多柒爵,網(wǎng)上有很多詳盡的資料役电,我這里就簡單介紹好了。錨點(diǎn)的值在0~1
的范圍內(nèi)棉胀,賦予其他值會(huì)被修正法瑟,默認(rèn)是在中心點(diǎn)(0.5,0.5)
,其位置如下所示:
(0,1)—————————(1,1)
| |
| (0.5,0.5) |
| |
(0,0)—————————(1,0)
-
position(位置)
→ 自身錨點(diǎn)相對于父節(jié)點(diǎn)錨點(diǎn)的位置
請務(wù)必注意膏蚓,如果先設(shè)置 position
調(diào)整好節(jié)點(diǎn)的位置瓢谢,之后又修改了 anchorPoint
會(huì)導(dǎo)致節(jié)點(diǎn)的坐標(biāo)出現(xiàn)偏移,當(dāng)然也可以通過拓展節(jié)點(diǎn)來優(yōu)化坐標(biāo)計(jì)算驮瞧。
在Constants.swift
文件中添加新的常量:
// 默認(rèn)錨點(diǎn)氓扛,通過這個(gè)值統(tǒng)一子節(jié)點(diǎn)的位置計(jì)算
public let kAnchorPoint = CGPoint(x: 0.5, y: 0.5)
在Extensions.swift
文件中添加新的拓展:
public extension SKSpriteNode {
var autoPosition: CGPoint {
set {
let realWidth = frame.width / kImageScale
let realHeight = frame.height / kImageScale
position = CGPoint(x: (newValue.x + (realWidth * (anchorPoint.x - kAnchorPoint.x))) * kImageScale, y: (newValue.y + (realHeight * (anchorPoint.y - kAnchorPoint.y))) * kImageScale)
} get {
return position
}
}
var autoAnchorPoint: CGPoint {
set {
anchorPoint = CGPoint(x: limit(newValue.x), y: limit(newValue.y))
position = CGPoint(x: (position.x + (frame.width * (anchorPoint.x - kAnchorPoint.x))), y: (position.y + (frame.width * (anchorPoint.y - kAnchorPoint.y))))
} get {
return anchorPoint
}
}
// 限制值的范圍在0~1之間
private func limit(_ num: CGFloat) -> CGFloat {
return max(0, min(num, 1))
}
}
之后對節(jié)點(diǎn)的 autoPosition
和 autoAnchorPoint
進(jìn)行設(shè)置,無論怎么怎么改變錨點(diǎn)的位置论笔,統(tǒng)一以錨點(diǎn)在(0.5,0.5)
來計(jì)算位置采郎。
給節(jié)點(diǎn)添加動(dòng)畫
上面我們介紹了 anchorPoint
,如果我們給節(jié)點(diǎn)添加動(dòng)作 SKAction
的話狂魔,需要注意動(dòng)作是基于anchorPoint
來進(jìn)行的蒜埋,如果默認(rèn)的錨點(diǎn)位置不能達(dá)成想要的動(dòng)畫效果,就需要通過修改錨點(diǎn)來調(diào)整動(dòng)畫效果了最楷。
我們在Functions.swift
文件中添加通用角度轉(zhuǎn)換的方法:
public func angle(_ angle: CGFloat) -> CGFloat {
return angle * CGFloat.pi / 180
}
接著在GameScene.swift
文件中添加setupCarrot()
方法并進(jìn)行調(diào)用
func setupCarrot() {
// 加載紋理
let carrot = SKSpriteNode(texture: Mainscene1_hd.carrot)
carrot.autoPosition = CGPoint(x: 0, y: 45)
let leaf1 = SKSpriteNode(texture: Mainscene1_hd.leaf_1)
leaf1.autoPosition = CGPoint(x: -65, y: 130)
let leaf2 = SKSpriteNode(texture: Mainscene1_hd.leaf_2)
leaf2.autoPosition = CGPoint(x: 5, y: 160)
let left3 = SKSpriteNode(texture: Mainscene1_hd.leaf_3)
left3.autoPosition = CGPoint(x: 60, y: 140)
// 修改錨點(diǎn)整份,添加動(dòng)畫
leaf2.autoAnchorPoint = CGPoint(x: 0.4, y: 0)
leaf2.run(.sequence([
.rotate(toAngle: angle(-10), duration: 0),
.wait(forDuration: 2),
.repeatForever(rotateAction())
]))
// 修改錨點(diǎn),添加動(dòng)畫
left3.autoAnchorPoint = CGPoint(x: 0.2, y: 0)
left3.run(.sequence([
.wait(forDuration: 6),
.repeatForever(rotateAction())
]))
// 添加節(jié)點(diǎn)
addChild(leaf1)
addChild(left3)
addChild(leaf2)
addChild(carrot)
// 添加上層標(biāo)題節(jié)點(diǎn)
let codebg = SKSpriteNode(texture: Mainscene1_hd.mainbg_cn)
codebg.position = CGPoint(x: -14, y: -54)
addChild(codebg)
}
/// 根據(jù)已有角度生成搖晃SKAction
func rotateAction() -> SKAction {
return .sequence([
.rotate(byAngle: angle(10), duration: 0.1),
.rotate(byAngle: angle(10), duration: 0.1),
.rotate(byAngle: angle(10), duration: 0.1),
.rotate(byAngle: angle(-10), duration: 0.1),
.wait(forDuration: 8)
])
}
因?yàn)樘}卜的圖層在上方籽孙,所以需要修改添加順序烈评,也可以通過修改節(jié)點(diǎn)的zPosition
屬性改變精靈的層級(jí)來達(dá)到效果,zPosition
默認(rèn)是0犯建,數(shù)值越大讲冠,節(jié)點(diǎn)層級(jí)越高
動(dòng)作效果如下:
關(guān)于動(dòng)作SKAction
在前面我們給節(jié)點(diǎn)添加了動(dòng)作, SKAction 是我們生成動(dòng)畫的核心類适瓦,下面簡單介紹一下它的幾個(gè)重要屬性和方法:
duration
→ 動(dòng)作時(shí)長竿开,通常在初始化動(dòng)作的時(shí)候設(shè)置,動(dòng)作組會(huì)自動(dòng)計(jì)算時(shí)長speed
→ 動(dòng)作速度玻熙,默認(rèn)值是1.0否彩,像游戲中的二倍速、三倍速可以通過調(diào)節(jié)這個(gè)屬性了達(dá)成效果move(to location: CGPoint, duration: TimeInterval) -> SKAction
→ 節(jié)點(diǎn)位置移動(dòng)方法嗦随,創(chuàng)建一個(gè)移動(dòng)到坐標(biāo)點(diǎn)location
的動(dòng)作胳搞,動(dòng)作時(shí)間為duration
。該動(dòng)作不可逆,動(dòng)作結(jié)束后保持移動(dòng)的位置肌毅。還有其他單獨(dú)移動(dòng)x軸moveTo(x: CGFloat, duration: TimeInterval)
和單獨(dú)移動(dòng)y軸moveTo(y: CGFloat, duration: TimeInterval)
的方法筷转。在本次項(xiàng)目中經(jīng)常應(yīng)用的就是怪物和炮塔子彈的移動(dòng)了。move(by delta: CGVector, duration: TimeInterval) -> SKAction
→ 節(jié)點(diǎn)位置移動(dòng)方法悬而,動(dòng)作可逆呜舒,創(chuàng)建一個(gè)x軸和y軸偏移的動(dòng)作,delta
包含了x軸和y軸的偏移量笨奠。rotate(byAngle radians: CGFloat, duration: TimeInterval) -> SKAction
→ 節(jié)點(diǎn)旋轉(zhuǎn)方法袭蝗,基于原有角度進(jìn)行相對角度旋轉(zhuǎn),每次旋轉(zhuǎn)不改變節(jié)點(diǎn)的原有角度般婆,動(dòng)作結(jié)束后回到原有角度到腥。rotate(toAngle radians: CGFloat, duration: TimeInterval) -> SKAction
→ 節(jié)點(diǎn)旋轉(zhuǎn)方法,基于傳入角度進(jìn)行絕對角度旋轉(zhuǎn)蔚袍,每次旋轉(zhuǎn)都改變節(jié)點(diǎn)的原有角度乡范,動(dòng)作結(jié)束后保持旋轉(zhuǎn)角度。
根據(jù)上面的介紹啤咽,大家應(yīng)該能夠觀察到 SKAction
各種動(dòng)作的規(guī)律了晋辆,使用 by
都是基于現(xiàn)有狀態(tài)的相對變化,使用 to
是一種絕對變化宇整,根據(jù)自己的需求使用對應(yīng)的方法吧瓶佳。
關(guān)于 SKAction
的其他動(dòng)作還有很多,這里就最終介紹已經(jīng)使用了的剩余相關(guān)動(dòng)作:
sequence(_ actions: [SKAction]) -> SKAction
→ 根據(jù)動(dòng)作組創(chuàng)建一個(gè)串行隊(duì)列動(dòng)作鳞青,如果了解過線程概念的應(yīng)該都比較懂霸饲,串行隊(duì)列中的動(dòng)作會(huì)按順序來運(yùn)行,如果使用動(dòng)作的reversed()
方法會(huì)會(huì)使串行隊(duì)列的動(dòng)作變成逆向運(yùn)行臂拓,例如:[1,2,3] -> [3R,2R,1R]
贴彼。group(_ actions: [SKAction]) -> SKAction
→ 根據(jù)動(dòng)作組創(chuàng)建一個(gè)并行隊(duì)列動(dòng)作,并行隊(duì)列中的動(dòng)作會(huì)同時(shí)進(jìn)行埃儿,總動(dòng)作時(shí)長是由隊(duì)列中動(dòng)作的最長時(shí)間決定的。wait(forDuration duration: TimeInterval) -> SKAction
→ 等待一定時(shí)間融涣。repeatForever(_ action: SKAction) -> SKAction
→ 動(dòng)作一直循環(huán)童番。repeat(_ action: SKAction, count: Int) -> SKAction
→ 動(dòng)作循環(huán)一定次數(shù)。
總結(jié)
在這次開發(fā)過程中威鹿,我們創(chuàng)建了新項(xiàng)目剃斧,也學(xué)習(xí)了紋理集和簡單動(dòng)畫的使用,對于簡單的頁面布置應(yīng)該沒什么問題了忽你,接下來就是時(shí)間的活啦幼东,讓我們來把首頁鋪滿吧!
在下次的學(xué)習(xí)中,我們將學(xué)習(xí)節(jié)點(diǎn)的點(diǎn)擊事件和場景切換根蟹,也會(huì)開始制作選關(guān)界面脓杉!
在學(xué)習(xí)過程中,我學(xué)習(xí)了很多文章简逮,也搬運(yùn)了一個(gè)流程比較清晰的游戲項(xiàng)目開發(fā)教程球散,大家可以先參考下面的文章,加深對SpriteKit的了解