删除SKAction并恢复节点状态



所需的行为是:当一个动作从节点中移除时(例如removeAction(forKey:)(,它会停止设置动画,并且会丢弃由动作引起的所有更改,因此节点会返回到以前的状态。换句话说,我想要实现类似于CAAnimation的行为。

但是,当SKAction被移除时,该节点保持不变。这不好,因为要恢复它的状态,我需要确切地知道删除了什么操作。如果我改变了操作,我还需要更新节点状态恢复。

更新:
特殊目的是在第三场比赛中展示可能的移动。当我展示动作时,片段开始跳动(scale动作,永远重复(。当用户移动时,我想停止显示移动,所以我删除了该操作。因此,作品可能会继续缩小规模。后来我想添加更多花哨和复杂的动画,所以我想能够轻松地编辑它。

感谢您的帮助和回答,我找到了自己的解决方案。我认为这里的国家机器有点太重了。相反,我创建了一个包装器节点,其主要目的是运行动画。它还有一个状态:isAimating属性。但是,首先,它允许startAnimating()stopAnimating()方法彼此靠近、封装,因此更难搞砸。

class ShowMoveAnimNode: SKNode {
let animKey = "showMove"
var isAnimating: Bool = false {
didSet {
guard oldValue != isAnimating else { return }
if isAnimating {
startAnimating()
} else {
stopAnimating()
}
}
}
private func startAnimating() {
let shortPeriod = 0.2
let scaleDown = SKAction.scale(by: 0.75, duration: shortPeriod)
let seq = SKAction.sequence([scaleDown,
scaleDown.reversed(),
scaleDown,
scaleDown.reversed(),
SKAction.wait(forDuration: shortPeriod * 6)])
let repeated = SKAction.repeatForever(seq)
run(repeated, withKey: animKey)
}
private func stopAnimating() {
removeAction(forKey: animKey)
xScale = 1
yScale = 1
}
}

用法:只需将应该设置动画的所有内容添加到此节点即可。适用于简单的动画,如:淡入淡出、缩放和移动。

@Knight0fDragon建议您最好使用GKStateMachine功能,我将给您举一个例子。

首先在场景中声明玩家/角色的状态

lazy var playerState: GKStateMachine = GKStateMachine(states: [
Idle(scene: self),
Run(scene: self)
])

然后你需要为这些状态中的每一个创建一个类,在这个例子中,我只向你展示Idle

import SpriteKit
import GameplayKit
class Idle: GKState {
weak var scene: GameScene?
init(scene: SKScene) {
self.scene = scene as? GameScene
super.init()
}
override func didEnter(from previousState: GKState?) {
//Here you can make changes to your character when it enters this state, for example, change his texture.
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is Run.Type //This is pretty obvious by the method name, which states can the character go to from this state.
}
override func update(deltaTime seconds: TimeInterval) {
//Here is the update method for this state, lets say you have a button which controls your character velocity, then you can check if the player go over a certain velocity you make it go to the Run state.
if playerVelocity > 500 { //playerVelocity is just an example of a variable to check the player velocity.
scene?.playerState.enter(Run.self)
}
}
}

当然,现在在场景中,您需要做两件事,第一件事是将角色初始化到某个状态,否则它将保持无状态,因此您可以在didMove方法中实现这一点。

override func didMove(to view: SKView) {
playerState.enter(Idle.self)
} 

最后但同样重要的是确保场景更新方法调用状态更新方法。

override func update(_ currentTime: TimeInterval) {
playerState.update(deltaTime: currentTime)
}

最新更新