動作
- 以點的方式移動
let actionMoveToPoint = SKAction.move(to: CGPoint(x: 100, y: 100), duration: 5)
let actionMoveToX = SKAction.moveTo(x: 700, duration: 2)
let actionMoveToY = SKAction.moveTo(y: 500, duration: 2)
- 以偏移量的方式移動
let actionMoveByPoint = SKAction.moveBy(x: 100, y: 100, duration: 5)
let actionMoveByV = SKAction.move(by: CGVector(dx: 100, dy: 100), duration: 5)
動作序列 (以let scene = GameAction()方式創建)
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let sprite : SKSpriteNode = SKSpriteNode(imageNamed: "1.png")
sprite.position = CGPoint(x: size.width * 0.5,
y: size.height * 0.5)
sprite.setScale(1)
self.addChild(sprite)
//創建并設置節點移動的動作,即斜向下移動(100,-100)
let actionMidMove = SKAction.move(to: CGPoint(x: size.width * 0.5 + 100,y: size.height * 0.5 - 100), duration: 2.5)
//創建并設置節點移動的動作,即斜向上移動(200,0)
let actionMove = SKAction.move(to: CGPoint(x: size.width * 0.5 + 200,y: size.height * 0.5),duration: 2.5)
//創建序列動作
let squence = SKAction.sequence([actionMidMove,actionMove])
sprite.run(squence)
}
}
重復動作
//創建序列動作
let squence = SKAction.sequence([actionMidMove,actionMove])
// sprite.run(squence)
//重復動作
let repeatAction = SKAction.repeat(squence, count: 5)
sprite.run(repeatAction)
重復動作的注意點 : 注意設計具體需要重復的路線就好
延遲動作
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node1 = SKSpriteNode()
node1.position = CGPoint(x: 0, y: size.height * 0.5)
node1.anchorPoint = CGPoint(x: 0, y: 0)
node1.color = UIColor.red
node1.size = CGSize(width: 100, height: 100)
self.addChild(node1)
let node2 = SKSpriteNode()
node2.position = CGPoint(x: 0, y: size.height * 0.5)
node2.anchorPoint = CGPoint(x: 0, y: 1)
node2.color = UIColor.blue
node2.size = CGSize(width: 100, height: 100)
self.addChild(node2)
//創建并設置節點移動的動作,向前300
let actionMoveForward = SKAction.move(to: CGPoint(x:300,y: size.height * 0.5), duration: 1.0)
//創建并設置節點移動的動作,回到原點
let actionMoveBackward = SKAction.move(to: CGPoint(x: 0,y: size.height * 0.5),duration: 1.0)
let waitAction1 = SKAction.wait(forDuration: 1)
let squence1 = SKAction.sequence([actionMoveForward,waitAction1,actionMoveBackward])
let repeatAction1 = SKAction.repeat(squence1, count: 5)
node1.run(repeatAction1)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0) {
let waitAction2 = SKAction.wait(forDuration: 1.0)
let squence2 = SKAction.sequence([actionMoveForward,waitAction2,actionMoveBackward])
let repeatAction2 = SKAction.repeat(squence2, count: 5)
node2.run(repeatAction2)
}
}
}
延時動作
縮放動作
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node = SKSpriteNode()
node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
node.color = UIColor.red
node.size = CGSize(width: 100, height: 100)
self.addChild(node)
let zoom = SKAction.scale(by: 2, duration: 0.5)
let skrink = SKAction.scale(by: 0.5, duration: 0.5)
let squence = SKAction.sequence([zoom,skrink])
let repeatAction = SKAction.repeat(squence, count: 5)
node.run(repeatAction)
}
}
縮放
PS : 這里要注意的是縮放的比例的控制
旋轉動作
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node = SKSpriteNode()
node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
node.color = UIColor.red
node.size = CGSize(width: 100, height: 100)
self.addChild(node)
let rotate = SKAction.rotate(byAngle: CGFloat.pi/4.0, duration: 0.25)
let repeatAction = SKAction.repeat(rotate, count: 10)
node.run(repeatAction)
}
}
旋轉
調整尺寸
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node = SKSpriteNode()
node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
node.color = UIColor.red
node.size = CGSize(width: 100, height: 100)
self.addChild(node)
let resizeWidth = SKAction.resize(toWidth: 300, duration: 1)
let wait = SKAction.wait(forDuration: 1)
let resizeHeight = SKAction.resize(toHeight: 300, duration: 1)
let squence = SKAction.sequence([resizeWidth,wait,resizeHeight])
node.run(squence)
}
}
調整尺寸
調整尺寸和縮放有點類似,但是更精確
組合動作
組合動作就是在同時對兩個或兩個以上的動作進行執行.
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node = SKSpriteNode()
node.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
node.anchorPoint = CGPoint(x: 0.5, y: 0.5)
node.color = UIColor.red
node.size = CGSize(width: 100, height: 100)
self.addChild(node)
let resizeWidth = SKAction.resize(toWidth: 300, duration: 1)
let wait = SKAction.wait(forDuration: 1)
let resizeHeight = SKAction.resize(toHeight: 300, duration: 1)
let squence = SKAction.sequence([resizeWidth,wait,resizeHeight])
let rotate = SKAction.rotate(byAngle: CGFloat.pi/2, duration: 2)
let group = SKAction.group([squence,rotate])
node.run(group)
}
}
兩個動作同步一起做
改變透明度
- 不需要指定alpha值
let fadeOut = SKAction.fadeOut(withDuration: 1)
let fadeIn = SKAction.fadeIn(withDuration: 1)
- 指定alpha值
let fadeAlphaTo1 = SKAction.fadeAlpha(to: 1, duration: 1)
let fadeAlphaTo2 = SKAction.fadeAlpha(by: 0.5, duration: 1)
可以通過這種做一些,加載時候的效果.
改變顏色
- 改變混合因子
let color1 = SKAction.colorize(withColorBlendFactor: 0.3, duration: 1)
let color2 = SKAction.colorize(withColorBlendFactor: 0.8, duration: 1)
- 改變顏色和混合因子
let color = SKAction.colorize(with: UIColor.blue, colorBlendFactor: 1.0, duration: 1)
原圖
變換過程
最終過程
以動畫的形式改變紋理的動作
let f1 = SKTexture(imageNamed: "texture1.png")
let f2 = SKTexture(imageNamed: "texture2.png")
let f3 = SKTexture(imageNamed: "texture3.png")
let f4 = SKTexture(imageNamed: "texture4.png")
let textureArray = [f1,f2,f3,f4]
let playerSprite = SKSpriteNode(texture: f1)
playerSprite.position=CGPoint(x : 50,y : 170)
self.addChild(playerSprite)
let runRightAction = SKAction.animate(with: textureArray, timePerFrame: 0.1)
let runForever = SKAction.repeatForever(runRightAction)
let actionMove = SKAction.move(to: CGPoint(x: 100, y: playerSprite.position.y),duration: 5)
let group = SKAction.group([runForever, actionMove])
playerSprite.run(group)
移動1
移動2
以不斷切換紋理圖片的形式,做出節點在活動的假象.
不過感覺這里有個bug,有些時候切換紋理的時候會一閃一閃的,也就是切換第一張,正常,第二張就顯示不出來,第三張又好了的樣子.交錯顯示.但是呢,多運行幾次又正常了.應該是一個bug.不知道是什么鬼情況.(先不要在意,跳過這里,知道有這個細節,看看后續能否悟出原因,我用的是Xcode9,和iOS11.0的版本,也有可能是新版本里面的bug)
動作路徑
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node1 = SKSpriteNode()
node1.position = CGPoint(x: 150, y: size.height * 0.5 - 50)
node1.color = UIColor.red
node1.size = CGSize(width: 50, height: 50)
self.addChild(node1)
let node2 = SKSpriteNode()
node2.position = CGPoint(x: 200, y: size.height * 0.5)
node2.color = UIColor.blue
node2.size = CGSize(width: 50, height: 50)
self.addChild(node2)
//讓node1以矩形路徑運動
let playRect = CGRect(x: 0, y: 0, width: 100, height: 100)
let screenBorders = CGPath(rect: playRect, transform: nil)
let followAction1 = SKAction.follow(screenBorders, duration: 3)
let repeatAction1 = SKAction.repeatForever(followAction1)
node1.run(repeatAction1)
let node3 = SKSpriteNode()
node3.position = CGPoint(x: 400, y: size.height * 0.5 - 50)
node3.color = UIColor.red
node3.size = CGSize(width: 50, height: 50)
self.addChild(node3)
let node4 = SKSpriteNode()
node4.position = CGPoint(x: 450, y: size.height * 0.5)
node4.color = UIColor.blue
node4.size = CGSize(width: 50, height: 50)
self.addChild(node4)
//讓node1以圓形路徑運動
let playRect2 = CGRect(x: 400, y: size.height * 0.5 - 50, width: 100, height: 100)
let circle = CGPath(roundedRect: playRect2, cornerWidth: 50, cornerHeight: 50, transform: nil)
let followAction2 = SKAction.follow(circle, asOffset: false, orientToPath: true, duration: 5)
let repeatAction2 = SKAction.repeatForever(followAction2)
node3.run(repeatAction2)
}
}
運動軌跡
路徑考慮 : 這里面的路徑考慮從錨點出發,錨點根據設置的路徑來執行.
這里有些比較有意思的考慮點
- 矩形路徑 : 考慮的角度是紅色節點的錨點,也就是矩形參考紅色節點的錨點位置.x和y值為0,0,也就是初始點.每次路徑結束都會重新計算一次路徑.
- 圓形路徑 : 考慮的角度是圓本身的路徑,也就是圓形參考場景坐標系.每次路徑計算都是固定的值.
PS : 關于其他路勁,多嘗試一下吧.
反向運動
let actionMove = SKAction.moveTo(x: 100, duration: 1)
let reversed = actionMove.reversed()
速度
可以通過一個給定的速度值來改變場景中精靈或者其他節點執行動作的速度.
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node1 = SKSpriteNode()
node1.position = CGPoint(x: 50, y: size.height * 0.5 - 50)
node1.color = UIColor.red
node1.size = CGSize(width: 50, height: 50)
self.addChild(node1)
let moveAction = SKAction.moveTo(x: 550, duration: 20)
let scaleAction = SKAction.scale(to: 2.5, duration: 20)
let speedAction = SKAction.speed(to: 5, duration: 1)
let group = SKAction.group([speedAction,moveAction,scaleAction])
node1.run(group)
}
}
速度動作
- 動作的 speed 屬性改變動畫播放的速率。你可以在動畫默認計時上加速或減速。
- speed 值為 1.0 是正常的速度。如果動作的 speed 屬性設置為 2.0,當節點執行動作時,
- 它速度快了一倍。要暫停動作,將值設置為 0。 如果你調整那些包含其他動作(例如組、序列或重復動作)的動作的速率,速率會應用到所
包含的動作。附加的動作也會受到它們自己的 speed 屬性的作用。 - 節點的 speed 屬性與動作的 speed 屬性具有相同的效果,但該速率適用于該節點或景樹中的任意后代所處理的所有動作。
簡單粗暴的理解 :
let speedAction = SKAction.speed(to: 0, duration: 4)
在4秒鐘之后,動作執行的速度變為0
顯示或隱藏
let hide = SKAction.hide()
let unhide = SKAction.unhide()
動作塊
有時候,開發者需要將一系列的動作放入到一個塊中,此時就是需要使用動作塊.
簡單粗暴的理解 :
就是將某些固定的動作封裝在一個動作塊中,到時候直接調用就好了.
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node1 = SKSpriteNode()
node1.position = CGPoint(x: 50, y: size.height * 0.5 - 50)
node1.color = UIColor.red
node1.size = CGSize(width: 50, height: 50)
self.addChild(node1)
let block = SKAction.run {
let rotate = SKAction.rotate(byAngle: CGFloat.pi, duration: 2)
let runForever = SKAction.repeatForever(rotate)
node1.run(runForever)
}
node1.run(block)
}
}
自定義動作
import SpriteKit
import GameplayKit
class GameAction: SKScene {
override func didMove(to view: SKView) {
self.size = UIScreen.main.bounds.size
let node1 = SKSpriteNode()
node1.name = "node1"
node1.position = CGPoint(x: 250, y: size.height * 0.5 - 50)
node1.color = UIColor.red
node1.size = CGSize(width: 50, height: 50)
self.addChild(node1)
let duration : TimeInterval = 2
let blinkTimes = 2.0
//node : 節點運行操作的節點。
//elapsedTime : 在動畫中傳遞的時間量。根據withDuration給定的參數
let customAction1 = SKAction.customAction(withDuration: duration) { (node, elapsedTime) in
let slice = duration / blinkTimes
let remainder = elapsedTime.truncatingRemainder(dividingBy: 2)
node.isHidden = remainder > CGFloat(slice) / 2.0
print(elapsedTime)
}
let repeatAction = SKAction.repeatForever(customAction1)
node1.run(repeatAction)
//移動
let customAction2 = SKAction.customAction(withDuration: duration) { (node, elapsedTime) in
let moveAction = SKAction.moveTo(x: 500, duration: duration)
node.run(moveAction)
}
node1.run(customAction2)
}
}
理解 : 其實有點像動作塊,也還是一樣將自定義的動作打包.
動作屬性
- 速度 speed
- 時間 duration
- 曲線方式 timingMode
- SKActionTimingLinear 線性執行
- SKActionTimingEaseIn 淡入
- SKActionTimingEaseOut 淡出
- SKActionTimingEaseInEaseOut 淡入淡出
刪除動作
let remove = SKAction.removeFromParent()
這個比較好理解,也就是刪除節點的動作.