Sprite Kit 是iOS 7開始添加的一個(gè)新內(nèi)置框架。主要用于開發(fā)2D游戲咙边。支持內(nèi)容包括 精靈猜煮、各種特效(視頻次员、濾鏡遮罩),繼承了物理引擎等許多內(nèi)容王带。
SpriteKit常用的類:
SKSpriteNode ----- 用于繪制精靈的紋理
SKVideoNod ----- 用于播放視頻
SKLabelNode ----- 用于渲染文本
SKShapeNode ----- 用于渲染基于Core Graphics 路徑的形狀
SKEmitterNode ----- 用于創(chuàng)建和渲染粒子系統(tǒng)
SKCropNode ----- 用于使用遮罩來裁剪子節(jié)點(diǎn)
SKEffectNode ----- 用于使用遮罩來裁剪子節(jié)點(diǎn)
簡(jiǎn)單介紹一下SpriteKit淑蔚,下面介紹開始spriteKit 中基礎(chǔ)類的使用。
SKScene 場(chǎng)景
使用SKScene之前先說一下SKView愕撰,SKView 類是專門用來呈現(xiàn)Sprite Kit 的View刹衫,在這個(gè)類中可以渲染和管理一個(gè)SKScene,每個(gè)Scene中可以加載多個(gè)精靈搞挣,Scene可以管理精靈的行為带迟。
導(dǎo)入SpriteKit 創(chuàng)建SKScene:
func createScene() {
let skView = SKView.init(frame: self.view.bounds)
if(skView.scene == nil){
skView.showsFPS = true
skView.showsNodeCount = true
let scene = GameScene(size: skView.bounds.size)
skView.presentScene(scene)
}
self.view.addSubview(skView)
}
在使用時(shí),一般會(huì)將Scene子類化囱桨,在子類中設(shè)置它的屬性仓犬。在游戲中都會(huì)有多個(gè)場(chǎng)景,就會(huì)有場(chǎng)景切換蝇摸,單純的場(chǎng)景切換會(huì)顯得非常生硬婶肩,所以SpriteKit中提供了過度動(dòng)畫。
crossFadeWithDuration 交叉淡入淡出過渡動(dòng)畫
doorsCloseHorizontalWithDuration 從左右兩邊水平關(guān)閉
doorsCloseVerticalWithDuration 從上下兩邊垂直關(guān)閉
doorsOpenHorizontalWithDuration 從中間向左右兩邊水平打開
doorsOpenVerticalWithDuration 從中間向左右兩邊垂直打開
doorwayWithDuration 從中間向兩邊打開貌夕,新場(chǎng)景從后方向屏幕靠近
fadeWithColor 淡入淡出的過渡動(dòng)畫律歼,先變成指定顏色,再變成目標(biāo)場(chǎng)景
fadeWithDuration 淡入淡出的過渡動(dòng)畫啡专,先變成黑色险毁,再變成指定顏色
flipHorizontalWithDuration 以水平中軸線垂直翻轉(zhuǎn)
flipVerticalWithDuration 以垂直中中軸線水平翻轉(zhuǎn)
movenInWithDirection 新場(chǎng)景從指定方向移入
pushWithDirection 新場(chǎng)景從指定方向推入
revealWithDirection 舊場(chǎng)景向指定方向移除,新場(chǎng)景在舊場(chǎng)景下面
使用:skView.presentScene(scene, transition:SKTransition)
SKSpriteNode 精靈
精靈分為有紋理精靈和無紋理精靈们童,紋理精靈是常用的畔况,是我們把插圖放到場(chǎng)景中的方法,像游戲中的任務(wù)角色和背景等慧库。
使用方法跷跪,創(chuàng)建精靈:
let KScreenWidth = UIScreen.main.bounds.width
let KScreenHeight = UIScreen.main.bounds.height
func addNode() {
let texture = SKTexture.init(imageNamed: "ao.jpg") // 紋理
let splash = SKSpriteNode.init(texture: texture)
// let splash = SKSpriteNode.init(imageNamed: "ao.jpg")
splash.size = CGSize.init(width: KScreenWidth, height: KScreenHeight)
splash.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
// 設(shè)置錨點(diǎn)
// splash.anchorPoint = CGPoint.init(x: 0.0, y: 0.0)
// 精靈著色
splash.color = SKColor.green
splash.colorBlendFactor = 0.3 // 顏色混合因子0~1
splash.setScale(2) // 縮放 放大兩倍
// splash.xScale = 2 // 單獨(dú)縮放x
splash.zRotation = CGFloat(Double.pi)/2 // 旋轉(zhuǎn)
splash.alpha = 0.5
splash.isHidden = false
self.addChild(splash)
// splash.removeFromParent()
// removeAllChildren()
}
其中的錨點(diǎn)可以根據(jù)下面的圖理解
可以理解為將圖片訂在墻上,錨點(diǎn)相當(dāng)于釘子釘?shù)奈恢闷氚澹J(rèn)是(0.5, 0.5)吵瞻。
刪除精靈
splash.removeFromParent()
removeAllChildren()
SKLightNode
為了讓精靈更具有真實(shí)感,SpriteKit提供了SKLightNode作為光源節(jié)點(diǎn)甘磨。
SKLightNode 可以定義光源的顏色橡羞、陰影和衰減程度。繼承于SKNode济舆。為了在SKSpriteNode的效果更加逼真卿泽,SKSpriteNode 提供了normalTexture 屬性,用來儲(chǔ)存原貼圖的發(fā)現(xiàn)貼圖NormalMap滋觉。
SKLightNode常用屬性:
enabled 光源的開關(guān)
ambientColor 環(huán)境顏色签夭,默認(rèn)黑色(無)
lightColor 光的顏色齐邦,默認(rèn)白色
shadowColor 被精靈物體遮擋產(chǎn)生的陰影顏色
falloff 光源強(qiáng)度的衰減比率
categoryBitMask 光的種類,32位整數(shù)第租。SKSpriteNode的 lightingBItMask(被何種光照亮)侄旬、shadowedBitMask(被何種光產(chǎn)生陰影)、shadowCastBitMask(遮擋何種光線并產(chǎn)生陰影) 存儲(chǔ)著光的種類煌妈。
SKLightNode使用:
func addLightNode() {
backgroundColor = SKColor.black
// 創(chuàng)建精靈
let spriNode = SKSpriteNode.init(color: UIColor.white, size: CGSize.init(width: 300, height: 300))
spriNode.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
self.addChild(spriNode)
// 添加光源
let nodeNormMap = spriNode.texture?.generatingNormalMap()
spriNode.normalTexture = nodeNormMap
spriNode.lightingBitMask = 1 // 被何種光照
spriNode.name = "SprNOde"
let lightSprite = SKLightNode() //實(shí)例化光源
lightSprite.position = CGPoint.init(x: KScreenWidth/2 + 60, y: KScreenHeight/2) // 關(guān)照位置
lightSprite.name = "LightSptite"
lightSprite.categoryBitMask = 1 // 光的種類
self.addChild(lightSprite)
}
運(yùn)行結(jié)果截圖:
SKAction 動(dòng)作
SKAction是游戲中很重要的一部分儡羔,內(nèi)容很多啊,會(huì)寫的比較長(zhǎng)璧诵。首先預(yù)覽下內(nèi)容汰蜘,動(dòng)作的分類:動(dòng)作屬性、移動(dòng)動(dòng)作之宿、序列動(dòng)作族操、重復(fù)動(dòng)作、延遲動(dòng)作比被、縮放動(dòng)作色难、旋轉(zhuǎn)動(dòng)作、調(diào)整尺寸的動(dòng)作等缀、組合動(dòng)作枷莉、改變透明度的動(dòng)作、改變顏色的動(dòng)作尺迂、以動(dòng)畫的形式改變紋理的動(dòng)作笤妙、路徑動(dòng)作、反向運(yùn)動(dòng)噪裕、速度動(dòng)作蹲盘、顯示或隱藏動(dòng)作、塊動(dòng)作膳音、自定義動(dòng)作召衔、刪除動(dòng)作。
創(chuàng)建動(dòng)作方法
let spriteMoveUp = SKAction.moveBy(x: 300, y: 0, duration: 1.0) // X方向向右移100
1祭陷、移動(dòng)動(dòng)作
包括以點(diǎn)的方式移動(dòng)和 以偏移量的方式移動(dòng)
func nodeAction() {
let texture = SKTexture.init(imageNamed: "field") // 紋理
let background = SKSpriteNode.init(texture: texture)
background.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
background.size = CGSize.init(width: KScreenWidth, height: KScreenHeight)
self.addChild(background)
let ball = SKSpriteNode.init(imageNamed: "soccer")
ball.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
ball.setScale(1.05) // 縮放
ball.size = CGSize.init(width: 50, height: 50)
self.addChild(ball)
// 動(dòng)作 以點(diǎn)的方式移動(dòng)
let spriteMoveUp = SKAction.moveBy(x: 300, y: 0, duration: 1.0) // X方向向右移100
// ball.run(spriteMoveUp)
// 動(dòng)作 以偏移量的方式移動(dòng)
let negDelta = CGVector.init(dx: -300, dy: -100)
let actionMove = SKAction.move(by: negDelta, duration: 2)
ball.run(actionMove)
}
2苍凛、動(dòng)作屬性
speed 速度
duration 時(shí)間
timingMode 曲線方式
曲線方式包括四種:
SKActionTimingLinear 平均分布
SKActionTimingEaseIn 開始較慢,再加快
SKActionTimingEaseOut 開始快颗胡,再變慢
SKActionTimingEaseInEaseOut 開始慢毫深,再加快至中間吩坝,再變慢
let spriteMoveUp = SKAction.moveBy(x: 300, y: 0, duration: 1.0)
spriteMoveUp.speed = 1.3 // 速度
spriteMoveUp.timingMode = SKActionTimingMode.easeInEaseOut // 曲線方式
print(ball.speed) // 獲取并輸出動(dòng)作所需時(shí)間
3毒姨、 序列動(dòng)作
使用sequence() 方法實(shí)現(xiàn)。以上面移動(dòng)動(dòng)作為例钉寝,將spriteMoveUp弧呐、actionMove作為一個(gè)序列動(dòng)作然后執(zhí)行闸迷。
let sequence = SKAction.sequence([spriteMoveUp, actionMove])
ball.run(sequence)
4、重復(fù)動(dòng)作
重復(fù)動(dòng)作分為無限重復(fù)和有次數(shù)的重復(fù)俘枫,使用方法:
let sequence = SKAction.sequence([spriteMoveUp, actionMove])
// let runForever = SKAction.repeatForever(sequence) // 無限重復(fù)
let runRepeat = SKAction.repeat(sequence, count: 2) // 重復(fù)兩次(執(zhí)行兩次)
ball.run(runRepeat)
5腥沽、延遲動(dòng)作
使用waitForDuration()方法實(shí)現(xiàn)。以序列動(dòng)作為例鸠蚪,在序列中插入一個(gè)延遲動(dòng)作今阳。
let wait = SKAction.wait(forDuration: 1.0) // 延遲動(dòng)作(延遲1s)
let sequence = SKAction.sequence([spriteMoveUp, wait, actionMove])
ball.run(sequence)
6、縮放動(dòng)作
縮放動(dòng)作分為:以縮放倍數(shù)縮放(scaleTo()茅信、scaleXTo())盾舌、以增量值縮放(scaleBy()、scaleXBy())
func scaleAction() {
let ball = SKSpriteNode.init(imageNamed: "soccer")
ball.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
ball.size = CGSize.init(width: 50, height: 50) // 設(shè)置初始大)
self.addChild(ball)
// 以縮放倍數(shù)縮放
let shrink = SKAction.scale(to: 0.1, duration: 0.5) // 縮小
let zoom = SKAction.scale(to: 10, duration: 2) // 放大
// 對(duì)寬高進(jìn)行縮放
// let shrink = SKAction.scaleX(to: 0.1, duration: 3) // 縮小
// let zoom = SKAction.scale(to: 1, duration: 3) // 放大
let sequence = SKAction.sequence([shrink, zoom])
let runForever = SKAction.repeatForever(sequence)
// ball.run(runForever)
// 以增量值縮放
let scaleZoom = SKAction.scale(by: 1, duration: 0.2) // 放大
let scaleShrink = SKAction.scale(by: -1, duration: 0.2) // 縮小
// let scaleZoom = SKAction.scaleX(by: 1, duration: 0.2) // 放大
// let scaleShrink = SKAction.scaleX(by: -1, duration: 0.2) // 縮小
let scaleSequence = SKAction.sequence([scaleZoom, scaleShrink])
let scaleForever = SKAction.repeatForever(scaleSequence)
ball.run(scaleForever)
}
7蘸鲸、旋轉(zhuǎn)動(dòng)作
使用rotateByAngle()方法實(shí)現(xiàn)妖谴。
let rotate = SKAction.rotate(byAngle: CGFloat(Double.pi)*2, duration: 3)
ball.run(rotate)
8、調(diào)整尺寸的動(dòng)作
調(diào)整尺寸的動(dòng)作包括:以目標(biāo)值調(diào)整尺寸酌摇、以增量調(diào)整尺寸
let resizeWidth = SKAction.resize(toWidth: 100, height: 100, duration: 2) // 以目標(biāo)值調(diào)整尺寸
ball.run(resizeWidth)
let resize = SKAction.resize(byWidth: 200, height: 200, duration: 2) // 以增量調(diào)整尺寸
ball.run(resize)
9膝舅、組合動(dòng)作
就是同時(shí)對(duì)兩個(gè)及以上的動(dòng)作進(jìn)行執(zhí)行。使用group()方法實(shí)現(xiàn)窑多。
func groupAction() {
backgroundColor = SKColor.black
let star = SKSpriteNode.init(imageNamed: "star.jpg")
star.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
star.size = CGSize.init(width: 300, height: 300)
self.addChild(star)
let zoom = SKAction.scale(to: 1, duration: 0.2)
let shrink = SKAction.scale(to: 0.1, duration: 0.2)
let sequence = SKAction.sequence([zoom, shrink])
let rotate = SKAction.rotate(byAngle: CGFloat(Double.pi)*2, duration: 1.5)
let group = SKAction.group([sequence, rotate]) // 組合動(dòng)畫
let runForever = SKAction.repeatForever(group)
star.run(runForever)
}
10仍稀、改變透明度的動(dòng)作
有兩種,分別是不需要指定alpha值和指定alpha值(以目標(biāo)值指定埂息、以增量值指定)琳轿。
// 不需要指定alpha值
let fadeOut = SKAction.fadeOut(withDuration: 0.25)
let fadeIn = SKAction.fadeIn(withDuration: 0.25)
// 指定alpha值
let fadeOutAlpha = SKAction.fadeAlpha(to: 0, duration: 0.2) // 以目標(biāo)值指定
let fadeInAlpha = SKAction.fadeAlpha(to: 1, duration: 0.2)
let hide = SKAction.fadeAlpha(by: -1, duration: 0.2) // 以增量值指定
let show = SKAction.fadeAlpha(by: 1, duration: 0.2)
11、改變顏色的動(dòng)作
分為兩種:改變混合因子耿芹、改變顏色和混合因子崭篡。
// 改變混合因子
let color1 = SKAction.colorize(withColorBlendFactor: 0.8, duration: 0.5)
let color2 = SKAction.colorize(withColorBlendFactor: 0.0, duration: 0.5)
// 改變顏色和混合因子
let color = SKAction.colorize(with: SKColor.green, colorBlendFactor: 0.7, duration: 2)
12、以動(dòng)畫的形式改變紋理的動(dòng)作
使用animateWithTextures()方法實(shí)現(xiàn)
func animateTexturesAction() {
// 加載動(dòng)畫紋理
let textures = NSMutableArray.init()
for index in 4...13 {
let texture = SKTexture.init(imageNamed: "frame-\(index)")
textures.add(texture)
}
let playerSprite = SKSpriteNode.init(texture: textures.firstObject as? SKTexture)
playerSprite.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
self.addChild(playerSprite)
let runRightAction = SKAction.animate(with: textures as! [SKTexture], timePerFrame: 0.1)
let runForever = SKAction.repeatForever(runRightAction)
playerSprite.run(runForever)
}
13吧秕、路徑動(dòng)作
使用followPath()方法實(shí)現(xiàn)琉闪。方法中的屬性:
path 用來指定一個(gè)CGPathRef路徑
offset 用來指定路徑中的點(diǎn)是否為相對(duì)坐標(biāo),true(相對(duì)坐標(biāo))砸彬,false(絕對(duì)坐標(biāo))
orient 指定Z軸在旋轉(zhuǎn)時(shí)屬性是否改變
sec 動(dòng)作時(shí)間
func pathAction() {
let background = SKSpriteNode.init(imageNamed: "field")
background.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
background.size = CGSize.init(width: KScreenWidth, height: KScreenHeight)
self.addChild(background)
let ball = SKSpriteNode.init(imageNamed: "soccer")
ball.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
ball.size = CGSize.init(width: 50, height: 50)
self.addChild(ball)
let circle = CGPath.init(roundedRect: CGRect.init(x: 200, y:100 , width: 200, height: 200), cornerWidth: 100, cornerHeight: 100, transform: nil)
let follow = SKAction.follow(circle, asOffset: false, orientToPath: false, duration: 5)
let runRepeat = SKAction.repeatForever(follow)
// 反向運(yùn)動(dòng)
let reverse = runRepeat.reversed()
// 速度動(dòng)作
let speedaction = SKAction.speed(to: 15, duration: 1.0)
let group = SKAction.group([speedaction, reverse])
ball.run(group)
}
14颠毙、反向運(yùn)動(dòng)
let spriteMoveUp = SKAction.moveBy(x: 300, y: 0, duration: 1.0)
let reverse = spriteMoveUp.reversed() // 反向運(yùn)動(dòng)
15、速度動(dòng)作
使用 speedTo() 或者 speedBy() 實(shí)現(xiàn)砂碉。
let speedaction = SKAction.speed(to: 5, duration: 1.0)
16蛀蜜、顯示或隱藏動(dòng)作
使用 hide() 和unhide()方法實(shí)現(xiàn)
let hide = SKAction.hide() // 顯示動(dòng)作
let show = SKAction.unhide() // 隱藏動(dòng)作
17、塊動(dòng)作
使用runBlock()方法實(shí)現(xiàn),異步調(diào)用動(dòng)作的方法闹究,可指定執(zhí)行的線程剪个。
func blockAction() {
let ball = SKSpriteNode.init(imageNamed: "soccer")
ball.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
ball.size = CGSize.init(width: 80, height: 80)
self.addChild(ball)
// 創(chuàng)建塊動(dòng)作
let blockAction = SKAction.run {
let rotate = SKAction.rotate(byAngle: CGFloat(Double.pi*2), duration: 3)
let runRepeat = SKAction.repeatForever(rotate)
ball.run(runRepeat)
}
ball.run(blockAction)
}
設(shè)置動(dòng)作執(zhí)行的線程:
SKAction.run({
}, queue: DispatchQueue)
18闸准、自定義動(dòng)作
使用customActionWithDuration()實(shí)現(xiàn)
func customAction() {
let background = SKSpriteNode.init(imageNamed: "field")
background.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
background.size = CGSize.init(width: KScreenWidth, height: KScreenHeight)
self.addChild(background)
let ball = SKSpriteNode.init(imageNamed: "soccer")
ball.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
ball.size = CGSize.init(width: 50, height: 50)
self.addChild(ball)
let customAction = SKAction.customAction(withDuration: 2) { (node: SKNode, elapsedTime: CGFloat) in
let fraction = CGFloat(elapsedTime) / 2.0
let yOff = 100 * 4 * fraction * (1 - fraction)
node.position = CGPoint.init(x: node.position.x, y: KScreenHeight/2 + CGFloat(yOff))
}
let runRepeat = SKAction.repeatForever(customAction)
ball.run(runRepeat)
// MARK: 刪除動(dòng)作
// let remove = SKAction.removeFromParent()
}
19霎奢、刪除動(dòng)作
使用removeFromParent()方法實(shí)現(xiàn)户誓。
let remove = SKAction.removeFromParent()
用戶交互
1、觸摸
觸摸是最常見的用戶交互之一幕侠。分為單拍帝美、多拍觸摸(touchesBegan),移動(dòng)觸摸(touchesMoved)晤硕,結(jié)束和取消觸摸(touchesEnded)悼潭。
在觸摸中常用的事件處理:?jiǎn)闻暮投嗯挠|摸在一個(gè)方法中監(jiān)聽,所以需要進(jìn)行區(qū)分
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let mytouches = touches as NSSet
let touch: AnyObject? = mytouches.anyObject() as AnyObject
if(touch?.tapCount == 1){
// 單拍
}
if(touch?.tapCount == 2) {
// 多拍
}
}
在移動(dòng)觸摸中獲取當(dāng)前點(diǎn)擊的坐標(biāo)位置
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let mytouchs = touches as NSSet
let touch = mytouchs.anyObject() as! UITouch
let touchLocation = touch.location(in: self)
print(touchLocation)
}
2舞箍、手勢(shì)
常見的手勢(shì)識(shí)別器:
名稱 | 功能 |
---|---|
UITapGestureRecognizer | 輕拍 |
UIPinchGestureRecognizer | 捏 |
UISwipeGestureRecognizer | 滑動(dòng) |
UIRotationGestureRecognizer | 旋轉(zhuǎn) |
UIPanGestureRecognizer | 移動(dòng) |
UILongPressGestureRecognizer | 長(zhǎng)按 |
- 輕拍
分兩步女责,添加手勢(shì)、實(shí)現(xiàn)手勢(shì)方法创译。
func addGestureRecognizer() {
let tapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(self.handleTap))
self.view?.addGestureRecognizer(tapGestureRecognizer)
}
func handleTap() {
backgroundColor = UIColor.yellow
}
- 捏
捏 其實(shí)就是通過兩個(gè)手指的張合抵知,實(shí)現(xiàn)圖片的放大和縮小。
func addGestureRecognizer() {
let pinchGestureRecognizer = UIPinchGestureRecognizer.init(target: self, action: #selector(handlepin(recognizer:)))
self.view?.addGestureRecognizer(pinchGestureRecognizer)
}
var lastScale: CGFloat = 0.0
func handlepin(recognizer: UIPinchGestureRecognizer) {
self.view?.bringSubview(toFront: view!)
// 復(fù)原
if(recognizer.state == UIGestureRecognizerState.ended){
lastScale = 1.0
return
}
let scale: CGFloat = 1.0 - (lastScale - recognizer.scale)
let current: CGAffineTransform = recognizer.view!.transform
let newaa = current.scaledBy(x: scale, y: scale)
recognizer.view?.transform = newaa
lastScale = recognizer.scale
}
- 旋轉(zhuǎn)
通過旋轉(zhuǎn)手勢(shì)软族,兩個(gè)手指旋轉(zhuǎn)控制圖片旋轉(zhuǎn)刷喜。
func addGestureRecognizer() {
let rotationGestureRecognizer = UIRotationGestureRecognizer.init(target: self, action: #selector(handRotation(recognizer:)))
self.view?.addGestureRecognizer(rotationGestureRecognizer)
}
// 旋轉(zhuǎn)
func handRotation(recognizer: UIRotationGestureRecognizer) {
let rataion:CGFloat = recognizer.rotation
sprite.zRotation = -rataion
}
- 移動(dòng)
和觸摸中的touchesMoved類似效果,通過移動(dòng)手勢(shì)立砸,可以使圖片跟著手指的移動(dòng)手勢(shì)移動(dòng)掖疮。
func addGestureRecognizer() {
let panGestureRecognizer = UIPanGestureRecognizer.init(target: self, action: #selector(handPan(recognizer:)))
self.view?.addGestureRecognizer(panGestureRecognizer)
}
// 移動(dòng)
func handPan(recognizer: UIPanGestureRecognizer) {
let point = recognizer.location(in: self.view)
let pointY = (self.view?.frame.size.height)! - point.y
sprite.position = CGPoint.init(x: point.x, y: pointY)
}
- 滑動(dòng)
滑動(dòng)手勢(shì):UISwipeGestureRecognizer。在使用時(shí)可以使用direction屬性設(shè)置滑動(dòng)手勢(shì)滑動(dòng)的方向颗祝。
func addGestureRecognizer() {
let swipeLeftGestureRecognizer = UISwipeGestureRecognizer.init(target: self, action: #selector(handSwipeLeft)) // 向左滑動(dòng)
swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirection.left;
self.view?.addGestureRecognizer(swipeLeftGestureRecognizer)
let swipeRightGestureRecognizer = UISwipeGestureRecognizer.init(target: self, action: #selector(handSwipeRight)) // 向右滑動(dòng)
swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirection.right;
self.view?.addGestureRecognizer(swipeRightGestureRecognizer)
}
// 滑動(dòng)
func handSwipeLeft() {
let actionMove = SKAction.move(to: CGPoint.init(x: sprite.size.width/2, y: KScreenHeight/2), duration: 1)
sprite.run(actionMove)
}
func handSwipeRight() {
let actionMove = SKAction.move(to: CGPoint.init(x: KScreenWidth - sprite.size.width/2, y: KScreenHeight/2), duration: 1)
sprite.run(actionMove)
}
- 長(zhǎng)按
func addGestureRecognizer() {
let longPressGestureRecognizer = UILongPressGestureRecognizer.init(target: self, action: #selector(handLongPress))
self.view?.addGestureRecognizer(longPressGestureRecognizer)
}
// 長(zhǎng)按
func handLongPress() {
backgroundColor = UIColor.gray
}
3浊闪、重力感應(yīng)
重力感應(yīng)事件又被稱為加速計(jì)事件,屬于運(yùn)動(dòng)事件的一種螺戳。運(yùn)動(dòng)時(shí)間產(chǎn)生可以通過:傾斜搁宾、搖動(dòng)設(shè)備等。這些運(yùn)動(dòng)事件的檢測(cè)基于設(shè)設(shè)備的加速計(jì)或陀螺儀倔幼。需要訪問這些數(shù)據(jù)盖腿,需要通過coreMotion這個(gè)框架,coreMotion有提供訪問加速計(jì)和陀螺儀數(shù)據(jù)的接口损同。
導(dǎo)入coerMotion框架翩腐,實(shí)例化CMMotionManager()對(duì)象。
在使用重力感應(yīng)前膏燃,需要判斷設(shè)備是否支持重力感應(yīng):
import CoreMotion
var mManger:CMMotionManager = CMMotionManager()
override func didMove(to view: SKView) {
if(!mManger.isAccelerometerAvailable){
// 重力感應(yīng)不可用
}
}
在判斷設(shè)備支持重力感應(yīng)后茂卦。我們來做一個(gè)小功能,使用重力感應(yīng)來控制精靈對(duì)象的移動(dòng)组哩。
步驟:
- 1等龙、創(chuàng)建場(chǎng)景处渣。
- 2、判斷重力感應(yīng)是否可用而咆。
- 3、添加物理引擎幕袱,添加物理體暴备。
- 4、獲取重力感應(yīng)accelerometer的數(shù)據(jù)们豌。
- 5涯捻、根據(jù)數(shù)據(jù)移動(dòng)精靈。
代碼:
import Foundation
import UIKit
import SpriteKit
import CoreMotion
var mManger:CMMotionManager = CMMotionManager()
class GravityScene: SKScene {
var gravityBall = SKSpriteNode.init(imageNamed: "soccer")
override func didMove(to view: SKView) {
// 創(chuàng)建兩個(gè)精靈對(duì)象望迎,場(chǎng)景和移動(dòng)體
let background = SKSpriteNode.init(imageNamed: "field")
background.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
background.size = CGSize.init(width: KScreenHeight, height: KScreenWidth)
self.addChild(background)
gravityBall.position = CGPoint.init(x: KScreenWidth/2, y: KScreenHeight/2)
gravityBall.size = CGSize.init(width: 50, height: 50)
self.addChild(gravityBall)
// 判斷重力感應(yīng)是否可用
if(!mManger.isAccelerometerAvailable){
// 重力感應(yīng)不可用
let alert:UIAlertController = UIAlertController.init(title: "提示", message: "重力感應(yīng)不可用", preferredStyle: UIAlertControllerStyle.alert)
let cancel:UIAlertAction = UIAlertAction.init(title: "取消", style: UIAlertActionStyle.cancel, handler: nil)
alert.addAction(cancel)
self.getCurrentVC()?.present(alert, animated: true, completion: {
})
}else {
mManger.startAccelerometerUpdates()
}
// 添加物理引擎障癌,添加物理體
self.physicsBody = SKPhysicsBody.init(edgeLoopFrom: self.frame)
//創(chuàng)建矩形物理體
self.gravityBall.physicsBody = SKPhysicsBody.init(rectangleOf: self.gravityBall.frame.size)
self.gravityBall.physicsBody?.isDynamic = true // 能承受碰撞和其他外力作用
self.gravityBall.physicsBody?.affectedByGravity = false // 不承受重力影響
self.gravityBall.physicsBody?.mass = 0.2 // 給物體任意質(zhì)量,使移動(dòng)就會(huì)顯得自然
}
// 飛創(chuàng)移動(dòng)的方法
func ballUpdate() {
let data:CMAccelerometerData? = mManger.accelerometerData
// 獲取accelerometer數(shù)據(jù)
var value:Double? = data?.acceleration.x
if(value == nil){
value = 0
}
// 判斷設(shè)備傾斜方向
if(fabs(value!) > 0.2){
let fvector = CGVector.init(dx: 40*CGFloat(value!), dy: 0)
self.gravityBall.physicsBody?.applyForce(fvector)
}
}
override func update(_ currentTime: TimeInterval) {
ballUpdate()
}
// 當(dāng)前控制器響應(yīng)者
func getCurrentVC()->UIViewController?{
var result:UIViewController?
var window = UIApplication.shared.keyWindow
if window?.windowLevel != UIWindowLevelNormal{
let windows = UIApplication.shared.windows
for tmpWin in windows{
if tmpWin.windowLevel == UIWindowLevelNormal{
window = tmpWin
break
}
}
}
let fromView = window?.subviews[0]
if let nextRespnder = fromView?.next{
if nextRespnder.isKind(of: UIViewController.classForCoder()){
result = nextRespnder as? UIViewController
}else{
result = window?.rootViewController
}
}
return result
}
}
將此場(chǎng)景添加到控制器的視圖上顯示即可辩尊。
// 創(chuàng)建重力感應(yīng)場(chǎng)景
func createGravityScene() {
let skView = SKView.init(frame: self.view.bounds)
if(skView.scene == nil){
skView.showsFPS = true
skView.showsNodeCount = true
let scene = GravityScene(size: skView.bounds.size)
skView.presentScene(scene)
}
self.view.addSubview(skView)
}
最后完成的效果是涛浙,場(chǎng)景中的ball精靈會(huì)根據(jù)手機(jī)的左右傾斜方向來移動(dòng)。
最后奉上前面所有內(nèi)容的demo Sprite Kit 基礎(chǔ)
參考:《iOS游戲框架 Sprite Kit技術(shù)詳解》
基礎(chǔ)篇就這些了摄欲。接下來就是進(jìn)階部分了:Sprite Kit 進(jìn)階(音頻轿亮、視頻、粒子系統(tǒng))胸墙。 還有最后的高級(jí):Sprite Kit 高級(jí)(物理引擎我注、瓦片地圖)。會(huì)不定期更新迟隅,有興趣的可以關(guān)注下哦但骨。