SpriteKit - 对在多个 SKNode 上运行的多个 SKAction 进行排序
Posted
技术标签:
【中文标题】SpriteKit - 对在多个 SKNode 上运行的多个 SKAction 进行排序【英文标题】:SpriteKit - Sequencing multiple SKActions running on multiple SKNodes 【发布时间】:2018-02-12 23:28:07 【问题描述】:我非常了解 SKAction API,但在多个节点上运行顺序代码时,我无法获得良好的代码。
这是一个示例代码(简化):
import SpriteKit
class GameScene: SKScene
weak var node1: SKNode!
weak var node2: SKNode!
override func didMove(to view: SKView)
super.didMove(to: view)
cacheUI()
runSampleSequence()
private func cacheUI()
// Fetch nodes from associated SKS file
node1 = self.childNode(withName: "node1")!
node2 = self.childNode(withName: "node2")!
private func runSampleSequence()
// I want node1 to fadeIn
// then node2 to fadeIn
// then node1 to fadeOut
// then node2 to fadeOut
node1.run(SKAction.sequence([
SKAction.fadeIn(withDuration: 1),
SKaction.run [weak self] in
self.node2.run(SKAction.fadeIn(withDuration: 2))
,
SKAction.fadeOut(withDuration: 4),
SKaction.run [weak self] in
self.node2.run(SKAction.fadeOut(withDuration: 3))
]))
之前的代码将完美运行,但如果我们添加 node3、node4 会导致样板代码......我希望能够对其进行重构,以便更易于阅读和维护给定的规范。类似的东西:
// Does not compile
self.run(SKAction.sequence([
node1.fadeIn(withDuration: 1),
node2.fadeIn(withDuration: 2),
node1.fadeOut(withDuration: 4),
node2.fadeOut(withDuration: 3)
]))
我能做到这一点吗?我希望业务代码尽可能清晰。
SKAction.sequence(_:) 在使用 SKAction.run _ 时的行为如何,是否保证在最后一个 SKAction.run 块的指令执行后运行下一个操作(如果它本身执行异步调用呢? ) ?
额外问题:我在闭包捕获列表中将 self 设置为 weak 是否正确?因为我不希望在关闭游戏场景时将其作为强有力的参考。
已编辑: 好吧,类似的事情可以完成这项工作,但第二次褪色在第一次结束之前开始......
private func runSampleSequence()
// I want node1 to fadeIn
// then node2 to fadeIn
// then node1 to fadeOut
// then node2 to fadeOut
self.run(SKAction.sequence([
node1.fadeIn(withDuration: 1),
node2.fadeIn(withDuration: 2),
node1.fadeOut(withDuration: 4),
node2.fadeOut(withDuration: 3)
]))
通过从 SKNode 扩展返回操作:
extension SKNode
func fadeIn(withDuration: TimeInterval) -> SKAction
let action = SKAction.run
self.run(SKAction.fadeIn(withDuration: withDuration))
return action
//TODO: Extend for each base SKAction ...
【问题讨论】:
【参考方案1】:我能做到这一点吗?我希望业务代码显示得一样清晰 可能。
您可以使用 swift 扩展来使您的代码更具可读性。例如:
extension SKNode
//TODO: Rename method and variable to be more expressive
func runAnimationName(node2:SKNode)
self.run(SKAction.sequence([
SKAction.fadeIn(withDuration: 1),
SKAction.run
node2.run(SKAction.fadeIn(withDuration: 2))
,
SKAction.fadeOut(withDuration: 4),
SKAction.run
node2.run(SKAction.fadeOut(withDuration: 3))
]))
在使用 SKAction.run 时,SKAction.sequence(_:) 的行为如何? _ ,下一个动作是否保证在最后一个动作之后运行 SKAction.run 块的指令执行(如果它本身呢? 执行异步调用)?
是的,动作是按顺序执行的。此外,如果 SKAction
运行块内有异步调用,则下一个 SKAction
将不会等待该异步调用结束。
额外问题:我在闭包捕获中将 self 设置为 weak 是否正确 清单?因为我不希望它在 关闭游戏场景。
您没有在块中使用self
,因此您可以删除[weak self]
。
【讨论】:
谢谢,但是扩展只是隐藏了内部动画实现,还是一样的。我不能用我提供的第二个代码 sn-p 来编写它。我在块内使用 self ,因为 node2 隐式引用 self.node2 (我编辑了代码以添加它)。【参考方案2】:嗯,一种解决方案是将每个 SKAction.run _ 部分与具有相同持续时间的 SKAction.wait(_:) 分组(这很难看,序列调用应该自己处理它):
extension SKNode
func fadeIn(withDuration: TimeInterval) -> SKAction
let action = SKAction.group([
SKAction.wait(forDuration: withDuration),
SKAction.run
self.run(SKAction.fadeIn(withDuration: withDuration))
])
return action
//TODO: Extend for each base SKAction ...
【讨论】:
更新:为了未来的读者,为此创建了一个 GitHub 存储库:github.com/michael-martinez/MMNodeActions以上是关于SpriteKit - 对在多个 SKNode 上运行的多个 SKAction 进行排序的主要内容,如果未能解决你的问题,请参考以下文章
SpriteKit: NSInvalidArgumentException - 试图添加一个已经有父节点的 SKNode