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 无尽的跑步者父 SKNode

swift SpriteKit SKNode 类

在 SpriteKit 中禁用 SKNode 的旋转

SpriteKit: NSInvalidArgumentException - 试图添加一个已经有父节点的 SKNode

SpriteKit addChild(node: SKNode) 复数?

子类化使用 SpriteKit .sks 场景文件创建的 SKNode