Translate form http://www.raywenderlich.com/84434/sprite-kit-swift-tutorial-beginners
小貼士:這是從之前的一個很受歡迎的教程用Swift重寫出來的,并作為iOS8盛宴的一部分發(fā)布。</br>
就像眾多的超級英雄結(jié)合在一起一樣蛛枚,Sprite Kit和Swift是一個令人驚訝的組合。</br>
-
Sprite Kit
是制作iOS游戲的最好方式之一倚喂,它容易上手,強大而且完全受Apple官方支持瓣戚。 -
Swift
是一個非常簡單的語言端圈,尤其對于那些新進入iOS的人來說焦读,這是非常容易上手的。
在這個教程里舱权,你會學(xué)到如何使用Apple官方的2D游戲引擎來創(chuàng)建2D游戲矗晃,我們會使用Sprite Kit和Swift!</br>
你可以跟著這個教程學(xué)習(xí)宴倍,也可以直接跳過教程去看最后的項目代碼张症。當(dāng)然,我們的主題是忍者啊楚。
Note:這個教程在我心中有些特別吠冤,因為這個教程之前的版本是我們這個網(wǎng)站最早發(fā)布的教程之一。它使用一個完全不同的語言(Objective-C)和另一個游戲引擎(Cocos2d)編寫的恭理。時間過得真是快!
Sprite Kit 對比 Unity
有一個能夠替代Sprite Kit而且很受歡迎的游戲引擎叫做Unity郭变,Unity最早之前是一個3D引擎颜价,但是最近也開始在內(nèi)部支持2D。
所以诉濒,在你開始學(xué)習(xí)之前周伦,我建議你先想好Sprite Kit和Unity中哪個會是你的項目的最好選擇。
Sprite Kit的優(yōu)點
-
它直接編譯在iOS原生框架上
: 它沒有必要去下載額外的庫或者產(chǎn)生外部依賴未荒。你可以在不依靠額外的插件的情況下無縫的使用其他比如像iAd
专挪,In-App Purchases
等等之類的iOS框架。 -
它依賴你現(xiàn)有的技能
:如果已經(jīng)了解Swift和iOS的開發(fā)片排,你可以馬上學(xué)會Sprite Kit寨腔。 -
這是Apple官方提供的
:它給你了你遷移到所有Apple新產(chǎn)品支持的優(yōu)勢。 -
這是免費的
:這可能是最重要的原因了率寡!你可以在不花費一分錢的情況下獲得到所有的Sprite Kit的功能迫卢,Unity有一個免費的版本,但是它不包括Pro版本的所有功能(而且比如你如果要避免Unity的彈出界面冶共,你需要升級它)乾蛤。
Unity的優(yōu)點
-
跨平臺
這是最大的一點了,如果你使用Sprite Kit捅僵。你就定死在iOS環(huán)境下家卖,使用Unity,你可以隨意到處你的游戲到Android庙楚,Windows等等上荡。 -
虛擬場景設(shè)計
Unity在設(shè)計場景的時候非常簡單,Sprite Kit在iOS8也有一個場景設(shè)計工具醋奠,但是這對于Unity提供的來說非抽痪剩基礎(chǔ)伊佃。 -
資源商店
Unity內(nèi)建了一個資源商店,你可以為你的游戲在這個商店里面購買各種各樣的資源沛善,有很多組件資源能夠節(jié)省你不少的開發(fā)時間航揉。 -
更加強大
Unity比Sprite Kit含有更多地功能。
我應(yīng)該選擇哪個金刁?
這看過上面的之后應(yīng)該在想:”那么我應(yīng)該選擇哪個2D框架引擎呢帅涂?“
這個答案取決你想要的目標是什么情龄,這里是我的答案:
- 如果你是一個編程新手刊侯,并且想要專注學(xué)習(xí)iOS:使用Sprite Kit——它是內(nèi)建的燃观,學(xué)起來簡單椎瘟,你可以很好的完成删顶。
- 如果你需要跨平臺開發(fā)或者開發(fā)一個復(fù)雜的游戲:使用Unity——它非常強大而且靈活超埋。
如果你覺得Unity適合你续膳,可以看看我們的Unity教程或者我們的Unity視頻教程;
否則的話题山,繼續(xù)閱讀并且開始學(xué)習(xí)Sprite Kit坯临!
你好 Sprite Kit!
我們從使用Sprite Kit游戲模板創(chuàng)建一個Hello World例子開始焊唬,我們使用Xcode6創(chuàng)建。打開Xcode 選擇File\New\Project看靠,選擇iOS\Application\Game template赶促, 點擊繼續(xù)。
輸入項目名稱為SpriteKitSimpleGame挟炬, 語言為Swift鸥滨, 使用框架為SpriteKit,設(shè)備為iPhone谤祖,然后點擊繼續(xù)
在你的硬盤上選擇一個地方來保存你的項目婿滓,然后點擊創(chuàng)建,學(xué)則iPhone6模擬器泊脐,然后點擊運行按鈕空幻,在載入界面結(jié)束后:
Sprite Kit是通過場景的概念組織的,場景就是游戲里有層級的一系列熒幕容客,比如你會有一個場景來防止游戲的主要區(qū)域秕铛,還有一個場景來放世界地圖,在他們之間就有層級缩挑。
如果你看一下你的項目但两,你會看見模板已經(jīng)在你的項目中默認創(chuàng)建了一個叫做GameScene
的場景,打開GameScene.swift
文件你會發(fā)現(xiàn)這包含了一些代碼放置一段文字當(dāng)屏幕上供置,并在你點擊的時候加入一個宇宙飛船谨湘。
在這個教程中,你主要會和這個GameScene
場景打交道,但是在開始之前紧阔,你需要做一些改變坊罢,因為這個游戲是橫屏的而不是豎屏的。
準備工作
對于這個模板項目還有兩個問題擅耽,第一個問題是我們需要一個橫屏的活孩,而這個項目是豎屏的,選擇SpriteKitSimpleGame
的target乖仇,然后在Deployment Info
這些選項中憾儒,取消豎屏,然后只剩下向左橫屏和向右橫屏被勾上就像下面顯示的那樣:
其次乃沙,刪除GameScene.sks
文件起趾,在彈出的時候選擇移除到垃圾桶
,這個文件可以讓你可視化的在場景上設(shè)置精靈和其他組件,但是對于這個游戲警儒,這個游戲非常簡單的通過代碼加入元素训裆,所以你并不需要它。
接下來冷蚂,打開GameViewController.swift 然后 用下面的代碼替換里面的內(nèi)容:
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene(size: view.bounds.size)
let skView = view as SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.ignoresSiblingOrder = true
scene.scaleMode = .ResizeFill
skView.presentScene(scene)
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
GameViewController
除了他的View
是個SKView
之外他就是個普通的UIViewController
,這個View包含了一個Sprite Kit
的場景缭保。
在這里你在viewDidLoad()
中創(chuàng)建了一個GameScene
對象,并把它初始化為屏幕大小蝙茶。
這些就是準備工作,那么接下來讓我們在屏幕上畫點東西吧诸老。
加入精靈元素
首先隆夯,下載這個項目的資源,然后將這些資源拖拽到項目中别伏,請確認在拖進去的時候你選擇了拷貝到項目文件夾中
蹄衷,并選擇了SpriteKitSimpleGame
為Target。
然后打開GameScene.swift
然后用下面的代碼代替里面的內(nèi)容:
import SpriteKit
class GameScene: SKScene {
// 1
let player = SKSpriteNode(imageNamed: "player")
override func didMoveToView(view: SKView) {
// 2
backgroundColor = SKColor.whiteColor()
// 3
player.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
// 4
addChild(player)
}
}
讓我們一步一步來看這段代碼
1厘肮、這里定義了一個叫做player
的私有屬性愧口,這個屬性就是一個精靈元素,你可以看到类茂,創(chuàng)建一個精靈元素非常簡單耍属,只要使用這個圖片的名字就能創(chuàng)建。
2巩检、這里設(shè)置背景顏色就和App設(shè)置背景顏色一樣簡單厚骗。在這里你設(shè)置了背景色為白色。
3兢哭、你設(shè)置了這個精靈的位置為x為寬度的0.1领舰,y為居中。
4、你必須要將精靈加入到場景中去才能看到這個精靈冲秽,就和你要將Views加入其他的Views里面一樣舍咖。
Build 并 運行,忍者就出現(xiàn)在了屏幕上锉桑。
移動的怪物
接下來你就要加入一些怪物到你的場景中來和你的忍者戰(zhàn)斗排霉,為了讓事情變得有趣些,你需要讓怪物動起來刨仑,不然的話就沒有什么挑戰(zhàn)性了郑诺!所以,讓我們在屏幕的右邊創(chuàng)建一些怪物杉武,并給他加上移動到左邊的動作辙诞。
將下面的代碼加入到GameScene.swift
:
func random() -> CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(#min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}
func addMonster() {
// Create sprite
let monster = SKSpriteNode(imageNamed: "monster")
// Determine where to spawn the monster along the Y axis
let actualY = random(min: monster.size.height/2, max: size.height - monster.size.height/2)
// Position the monster slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
monster.position = CGPoint(x: size.width + monster.size.width/2, y: actualY)
// Add the monster to the scene
addChild(monster)
// Determine speed of the monster
let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
// Create the actions
let actionMove = SKAction.moveTo(CGPoint(x: -monster.size.width/2, y: actualY), duration: NSTimeInterval(actualDuration))
let actionMoveDone = SKAction.removeFromParent()
monster.runAction(SKAction.sequence([actionMove, actionMoveDone]))
}
我已經(jīng)加上了很多的注釋來讓大家更好地理解,首先我們要向之前討論那樣建立對象轻抱,你需要做一些簡單的計算來確定我們在哪里創(chuàng)建這個怪物對象飞涂,設(shè)置它的位置,然后就像你加入忍者一樣的加入怪物祈搜。
唯一不同的是我們這次要加入一些動作较店,Sprite Kit提供了很多極其簡便的內(nèi)建方式來幫助你改變精靈元素的狀態(tài),比如移動動作容燕,旋轉(zhuǎn)動作梁呈,漸變動作,動畫動作等等蘸秘,在這里你會對怪物使用三種動作官卡。
-
SKAction.moveTo(_:duration:)
:你使用這個方法讓對象橫跨屏幕到屏幕的左邊,注意你可以動過設(shè)置duration
來確定這大哥移動動畫的時間醋虏,我們這里使用一個2~4的隨機值寻咒。 -
SKAction.removeFromParent()
:Sprite Kit提供一個簡便的方法來將精靈節(jié)點從他的父節(jié)點移除,就是把它從場景移除的意思颈嚼,我們使用這個方法將怪物從場景中移除毛秘,這樣這個怪物就消失了,這點非常重要阻课,因為如果你不提供讓怪物對象消亡的方法叫挟,你的設(shè)備的內(nèi)存會被消耗光。 -
SKAction.sequence(_:)
:sequence
將我們想要執(zhí)行的方法序列化柑肴,使用這個東西可以先執(zhí)行“移動”的動作霞揉,等到這個完成了,再執(zhí)行“從父節(jié)點刪除”的動作晰骑。
在這些動作之前适秩,你必須要先調(diào)用創(chuàng)建怪物對象的方法绊序。為了讓這些更加有趣些,我們需要讓怪物連續(xù)不斷的出現(xiàn)在屏幕上秽荞。我們只需要在didMoveToView()
的最后加入以下代碼:
runAction(SKAction.repeatActionForever(
SKAction.sequence([
SKAction.runBlock(addMonster),
SKAction.waitForDuration(1.0)
])
))
這樣你就可以有序的調(diào)用在代碼塊中的動作(多虧了Swift的強大骤公,你可以無縫的在addMaster()中加入動作代碼),在完成后等待一秒鐘之后扬跋,你可以虛幻這個動作的序列阶捆。
好了!運行這個項目钦听,現(xiàn)在你可以欣喜的看見怪物在屏幕上移動洒试。
發(fā)射飛鏢!
這個時候朴上,忍者正在等著你給他下指令呢垒棋!那么讓我們發(fā)射飛鏢吧!有很多方式可以實現(xiàn)發(fā)射飛鏢痪宰,但是在這個游戲中叼架,我們需要完成的效果是當(dāng)用戶點擊屏幕的時候,忍者會向用戶點擊的方向發(fā)射飛鏢衣撬。
對于一個初學(xué)者來說乖订,我們會使用“移動”動作來實現(xiàn),但是要使用“移動“來實現(xiàn)我們需要做一些數(shù)學(xué)計算具练。
因為”移動“動作需要你告訴他一個飛鏢的目的地乍构,但是你點擊的位置只是指明一個方向,而不是飛鏢的目的地扛点,你要做的是讓飛鏢沿著手點擊的方向一直移動蜡吧,直到這個飛鏢飛出屏幕。
下面這張圖說明了這種情況:
你可以發(fā)現(xiàn)占键,你在原始點和點擊的點的之間建立了一個三角形,你需要建立一個等比的三角形元潘,然后你會直到這個點將會從屏幕的哪里飛出畔乙。
如果你對向量計算有所了解的話,你使用起這些計算會比較得心應(yīng)手翩概,但是Srpite Kit沒有默認的這些方法牲距,需要自己去實現(xiàn)。
非常幸運钥庇,多虧了強的Swift的運算符重載功能牍鞠,我們能夠非常簡單的實現(xiàn)這些功能。將這些方法加入到文件的頂部评姨,就在GameScene
之前难述。
func + (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x + right.x, y: left.y + right.y)
}
func - (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x - right.x, y: left.y - right.y)
}
func * (point: CGPoint, scalar: CGFloat) -> CGPoint {
return CGPoint(x: point.x * scalar, y: point.y * scalar)
}
func / (point: CGPoint, scalar: CGFloat) -> CGPoint {
return CGPoint(x: point.x / scalar, y: point.y / scalar)
}
#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
return CGFloat(sqrtf(Float(a)))
}
#endif
extension CGPoint {
func length() -> CGFloat {
return sqrt(x*x + y*y)
}
func normalized() -> CGPoint {
return self / length()
}
}
這些都是一些非常基礎(chǔ)的向量計算的實現(xiàn),如果你對這里為什么會這么做或者你是第一次接觸向量計算的話胁后,可以看一些這個網(wǎng)站迅速學(xué)期一下店读。
接下來,在文件中加入這個方法:
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
// 1 - Choose one of the touches to work with
let touch = touches.anyObject() as UITouch
let touchLocation = touch.locationInNode(self)
// 2 - Set up initial location of projectile
let projectile = SKSpriteNode(imageNamed: "projectile")
projectile.position = player.position
// 3 - Determine offset of location to projectile
let offset = touchLocation - projectile.position
// 4 - Bail out if you are shooting down or backwards
if (offset.x < 0) { return }
// 5 - OK to add now - you've double checked position
addChild(projectile)
// 6 - Get the direction of where to shoot
let direction = offset.normalized()
// 7 - Make it shoot far enough to be guaranteed off screen
let shootAmount = direction * 1000
// 8 - Add the shoot amount to the current position
let realDest = shootAmount + projectile.position
// 9 - Create the actions
let actionMove = SKAction.moveTo(realDest, duration: 2.0)
let actionMoveDone = SKAction.removeFromParent()
projectile.runAction(SKAction.sequence([actionMove, actionMoveDone]))
}
這里有很多知識點攀芯,我們還是一步一步來看代碼屯断。
1、一個非陈屡担酷的事情就是SpriteKit包含了UITouch的一些方法比如locationInNode(_:)
和previousLocationInNode(_:)
殖演,這些方法能讓你找到你在SKNode系統(tǒng)中的點擊事件,通過這點年鸳,你可以找到在SKNode的點擊位置趴久。
2、然后你在忍者的位置上面創(chuàng)建一個飛鏢對象阻星,這時候你還不需要將這個飛鏢加到場景中去朋鞍,因為你需要先進行檢測,因為我們的游戲不允許忍者向后發(fā)射飛鏢妥箕。
3滥酥、然后通過運算計算出點擊位置和忍者位置的向量。
4畦幢、如果X值小于或者等于0那么坎吻,這說明忍者將要向后發(fā)射,我們就直接return不做任何操作宇葱。
5瘦真、否則的話,將飛鏢加入到場景中黍瞧。
6诸尽、將獲得的向量轉(zhuǎn)換為長度為1的單位向量,這樣我們可以用這個向量更容易的得到我們所要的長度的向量印颤,因為1 * 長度 = 長度您机。
7、我們將這個單位向量乘以1000年局,為什么是1000际看?因為這樣會有足夠的長度讓飛鏢飛出屏幕。
8矢否、加入當(dāng)前的位置的數(shù)據(jù)仲闽,這樣我們就能知道飛鏢什么時候飛出屏幕。
9僵朗、最后像創(chuàng)建怪物對象一樣使用moveTo(_:, duration:)
方法和removeFromParent()
方法赖欣。
運行代碼屑彻,現(xiàn)在你的忍者就能夠向著成群飛來的怪物發(fā)射了!
碰撞檢測和物理效果
我們從在文件頭部加入下面這段代碼開始:
struct PhysicsCategory {
static let None : UInt32 = 0
static let All : UInt32 = UInt32.max
static let Monster : UInt32 = 0b1 // 1
static let Projectile: UInt32 = 0b10 // 2
}
This is setting up the constants for the physics categories you’ll need in a bit – no pun intended! :] (這句翻譯不好畏鼓,各位自己理解)
注意
:你會想這TM是什么語句酱酬,你會發(fā)現(xiàn)這個Sprite Kit的類是一個作為位掩碼的32位的Integer數(shù)據(jù),這個方式說明數(shù)字總的每一個位可以代表一個類(所以你最多能夠含有32個類)云矫。在這里膳沽,你設(shè)置第一位指向怪物對象,第二位指向飛鏢對象等等让禀。
接下來挑社,讓GameScene
實現(xiàn)SKPhysicsContactDelegate
接口:
class GameScene: SKScene, SKPhysicsContactDelegate {
然后,在didMoveToView(_:)
中在加入忍者之后加入這幾行代碼:
physicsWorld.gravity = CGVectorMake(0, 0)
physicsWorld.contactDelegate = self
這設(shè)置這個這個物理世界沒有重力巡揍,并且能夠?qū)蓚€物體的碰撞事件通過delegate傳遞到場景中痛阻。
在addMonster()
方法中,在創(chuàng)建怪物對象的后面插入這幾行代碼:
monster.physicsBody = SKPhysicsBody(rectangleOfSize: monster.size) // 1
monster.physicsBody?.dynamic = true // 2
monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster // 3
monster.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile // 4
monster.physicsBody?.collisionBitMask = PhysicsCategory.None // 5
我們一行一行來看這些代碼做了什么
1腮敌、為精靈元素創(chuàng)建SKPhysicsBody阱当,在這個栗子中,SKPhysicsBody是一個和精靈大小相同的矩形糜工,我們把這個當(dāng)做這個怪物的近似形狀弊添。
2、這只精靈元素是動態(tài)的捌木,這意味著物理引擎是不能控制這個精靈元素的移動的油坝,你可以通過代碼來設(shè)置這個精靈元素的移動。
3刨裆、設(shè)置精靈元素的bit mask
為我們之前定義的monsterCategory
澈圈。
4、contactTestBitMask
indicates what categories of objects this object should notify the contact listener when they intersect. You choose projectiles here.
5帆啃、The collisionBit
Mask indicates what categories of objects this object that the physics engine handle contact responses to (i.e. bounce off of). You don’t want the monster and projectile to bounce off each other – it’s OK for them to go right through each other in this game – so you set this to 0.(這兩段沒看懂)
接下來瞬女,在touchesEnded(_:withEvent:)
中,在設(shè)置飛鏢的地點之后加入下面代碼:
projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
projectile.physicsBody?.dynamic = true
projectile.physicsBody?.categoryBitMask = PhysicsCategory.Projectile
projectile.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
projectile.physicsBody?.collisionBitMask = PhysicsCategory.None
projectile.physicsBody?.usesPreciseCollisionDetection = true
可以自己嘗試著看懂這些代碼努潘,如果你還不懂拆魏,就回過頭去看看之前的講解。
第二個測試就是看看這兩段代碼有什么不一樣的地方慈俯。
接下來,定義一個飛鏢碰撞怪物之后的處理的方法拥峦,注意這個方法不會自動調(diào)用贴膘,你需要自己調(diào)用,
func projectileDidCollideWithMonster(projectile:SKSpriteNode, monster:SKSpriteNode) {
println("Hit")
projectile.removeFromParent()
monster.removeFromParent()
}
你在這里只是當(dāng)他們碰撞的時候從場景中移除怪物和飛鏢略号,很簡單刑峡!是嗎洋闽?
現(xiàn)在,是時候?qū)崿F(xiàn)delete了突梦,將下面這個新方法加到文件中
func didBeginContact(contact: SKPhysicsContact) {
// 1
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 2
if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
(secondBody.categoryBitMask & PhysicsCategory.Projectile != 0)) {
projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode)
}
}
因為你設(shè)置了這個場景為這個物理世界的代理诫舅,這個方法在每次兩個精靈經(jīng)行碰撞的時候都會調(diào)用。
這個方法有兩部分:
1宫患、這個方法傳遞了兩個碰撞的精靈元素刊懈,但是我們不能保證兩個精靈元素的前后順序,所以這些位掩碼可以幫助我們識別兩個精靈元素娃闲。
2虚汛、最后,判斷碰撞的兩個精靈元素是不是一個是怪物精靈皇帮,一個是飛鏢精靈卷哩,然后調(diào)用之前定義的那個方法。
運行程序属拾,現(xiàn)在将谊,當(dāng)你的飛鏢撞擊到目標的時候,他們就會消失渐白。
結(jié)束點擊
現(xiàn)在尊浓,你離一個非常好玩(但是非常簡單)的游戲已經(jīng)很近了,你現(xiàn)在只需要一些特效和音樂(當(dāng)然礼预,哪個游戲沒有音樂效果眠砾?)和一些簡單的游戲邏輯。
Sprite Kit本身沒有像cocos2D一樣帶有一個音頻引擎托酸,但是有一個好消息就是我們有個方法來根據(jù)動作來播放音樂褒颈,你可以使用AVFoundation來播放背景音樂。
你現(xiàn)在已經(jīng)一些我給的非忱ぃ酷炫的音樂谷丸,這會對你的項目產(chǎn)生非常棒的效果,這些音樂就在之前你加入項目的資源文件里面应结,你只需要播放他們刨疼!
為了實現(xiàn)這些,你需要在GameScene.swift
中加入這些代碼:
import AVFoundation
var backgroundMusicPlayer: AVAudioPlayer!
func playBackgroundMusic(filename: String) {
let url = NSBundle.mainBundle().URLForResource(
filename, withExtension: nil)
if (url == nil) {
println("Could not find file: \(filename)")
return
}
var error: NSError? = nil
backgroundMusicPlayer =
AVAudioPlayer(contentsOfURL: url, error: &error)
if backgroundMusicPlayer == nil {
println("Could not create audio player: \(error!)")
return
}
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play()
}
這些是一些AVFoundation的代碼鹅龄。
想要試一試這些揩慕,只要在didMoveToView(_:)
剛開始加入下面這些代碼:
playBackgroundMusic("background-music-aac.caf")
至于特效音樂,在touchesEnded(_:withEvent:)
加入下面代碼:
runAction(SKAction.playSoundFileNamed("pew-pew-lei.caf", waitForCompletion: false))
非常方便扮休,是不是迎卤?你只需要一行代碼就能播放音效了。
運行項目玷坠,享受這些音樂吧蜗搔!
游戲結(jié)束劲藐,小伙子!
現(xiàn)在讓我們新建一個場景來作為“獲勝”或者“失敗”頁面樟凄,新建文件iOS\Source\Swift File template
聘芜,為文件命名,然后點擊創(chuàng)建缝龄。
然后在GameOverScene.swift
中用下面代碼代替里面的內(nèi)容:
import Foundation
import SpriteKit
class GameOverScene: SKScene {
init(size: CGSize, won:Bool) {
super.init(size: size)
// 1
backgroundColor = SKColor.whiteColor()
// 2
var message = won ? "You Won!" : "You Lose :["
// 3
let label = SKLabelNode(fontNamed: "Chalkduster")
label.text = message
label.fontSize = 40
label.fontColor = SKColor.blackColor()
label.position = CGPoint(x: size.width/2, y: size.height/2)
addChild(label)
// 4
runAction(SKAction.sequence([
SKAction.waitForDuration(3.0),
SKAction.runBlock() {
// 5
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
let scene = GameScene(size: size)
self.view?.presentScene(scene, transition:reveal)
}
]))
}
// 6
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
這個代碼中有5個值得提及的部分:
1汰现、設(shè)置背景為白色,就和之前在主場景做的一樣二拐。
2服鹅、通過won參數(shù)來決定是“勝利”或者“失敗”。
3百新、這展示了應(yīng)該怎么在使用Sprite Kit在屏幕上放一個文字企软,正如你所見的,這非常簡單饭望,你只需要設(shè)置字體并定義一些參數(shù)仗哨。
4、最后铅辞,定義兩個有序的動作厌漂,剛開始先等待兩秒,然后它運行了代碼塊
5斟珊、這是我們切換場景的動畫苇倡,你可以在多種多樣的動畫中選擇一種方式來切換場景,在這里你選擇了Flip動畫囤踩,并設(shè)置動畫時間為0.5秒旨椒,然后你創(chuàng)建了一個你想要顯示的場景,然后使用self.view的presentScene(_:transition:)
方法來切換堵漱。
6综慎、如果你實現(xiàn)了場景的init方法,那么你必須也實現(xiàn)init(coder:)
方法勤庐, 雖然這個方法是不會被調(diào)用的示惊,所以你只需要隨便加上fatalError(_:)
之類的代碼。
這下好了愉镰,現(xiàn)在你只需要啟動你的主場景米罚,然后在適當(dāng)?shù)臅r候切換到游戲結(jié)束場景就好了。
切換回到GameScene.swift
丈探, 在addMonster()
中的最后加入下面的代碼:
let loseAction = SKAction.runBlock() {
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
let gameOverScene = GameOverScene(size: self.size, won: false)
self.view?.presentScene(gameOverScene, transition: reveal)
}
monster.runAction(SKAction.sequence([actionMove, loseAction, actionMoveDone]))
這設(shè)定了當(dāng)怪物走出了屏幕之后你就失敗了阔拳,如果你理解了所有的代碼,如果不參考教程對之前代碼的解釋,這里給你來個突擊檢測:你為什么要在actionMoveDone
之前運行loseAction
糊肠,如果你不知道會發(fā)生什么的話,你可以顛倒順序試試看遗锣。
現(xiàn)在你需要處理勝利的邏輯了货裹,別對你的玩家太殘忍了,在GameScene
的最上面加上一個新的屬性精偿,就放在Player
的下面:
var monstersDestroyed = 0
并且在projectile(_:didCollideWithMonster:):
最下面加上這些代碼:
monstersDestroyed++
if (monstersDestroyed > 30) {
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
let gameOverScene = GameOverScene(size: self.size, won: true)
self.view?.presentScene(gameOverScene, transition: reveal)
}
繼續(xù)運行項目弧圆,現(xiàn)在你就可以產(chǎn)生勝利和失敗的條件,并在適當(dāng)?shù)臅r候切換到游戲結(jié)束的場景笔咽!
看完這個該何去何從
結(jié)束了搔预,這是這個Sprite Kit Swift Tutorial for beginners
教程的全部代碼
我希望你能夠喜歡學(xué)習(xí)Sprite Kit并能夠有興趣自己做一個自己的游戲
如果你想逃學(xué)習(xí)更多地關(guān)于Sprite Kit的知識,你可以看一下我們的書《 iOS Games by Tutorials》