所需的行为是:当从节点(例如,以removeAction(forKey:)
)删除某个动作时,该动画将停止进行动画处理,并且由该动作引起的所有更改都将被丢弃,因此该节点返回到先前的状态。换句话说,我想要实现类似于CAAnimation
的行为。
但是当删除SKAction
时,该节点仍保持更改。这不好,因为要恢复它的状态,我需要确切地知道删除了什么操作。而且,如果我随后更改操作,则还需要更新节点状态还原。
更新:
特定目的是为了显示三消游戏中的可能动作。当我显示动作时,棋子开始跳动(scale
动作,永远重复)。当用户移动时,我想停止显示移动,因此我删除了该动作。结果,碎片可能会保持缩小。稍后,我想添加更多精美且复杂的动画,因此我希望能够轻松对其进行编辑。
答案 0 :(得分:2)
感谢有用的评论和答案,我提出了自己的解决方案。我认为状态机在这里会太重。相反,我创建了一个包装节点,其主要目的是运行动画。它还具有状态: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
}
}
用法:只需将应设置动画的所有内容添加到此节点。与简单的动画效果很好,例如:淡入淡出,缩放和移动。
答案 1 :(得分: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)
}