动作
- 以点的方式移动
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)
以不断切换纹理图片的形式,做出节点在活动的假象.
不过感觉这里有个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()
这个比较好理解,也就是删除节点的动作.