SKAction完成处理程序; 在Swift中的使用

12

我是Swift和SpriteKit的新手。许多SpriteKit Actions示例都是用Objective C编写的,而我又无法将其映射到Swift中或使其在Swift中运行。

如果运行一个SKAction,并希望在SKAction完成后执行其他操作,我该如何在Swift中实现呢?


    spaceMan.runAction(spaceManDeathAnimation, completion: {
        println("red box has faded out")
    })

非常感谢任何想法。

编辑:

for i in 0...29 {
    textures.append(SKTexture(imageNamed: "spaceManDeath_\(i)"))
}
spaceManDeathAnimation = SKAction.repeatActionForever(SKAction.animateWithTextures(textures, timePerFrame: 0.15625))

你需要的是在SKAction序列中运行一个块的SKAction。 - BotMaster
空间人死亡动画操作是做什么的?它是如何定义的?你能分享一下代码吗? - giorashc
1
搜索页面中的“completion”以获取一些很好的示例。http://www.gamefromscratch.com/post/2014/07/02/Game-development-tutorial-Swift-and-SpriteKit-Part-4-Actions.aspx - sangony
3个回答

6

这里发现了一个问题:

spaceManDeathAnimation = SKAction.repeatAction(SKAction.animateWithTextures(textures, timePerFrame: 0.15625), count: 1)

此外,正如sangony发布的非常不错的链接 - 解决了完成块语法问题。
    spaceMan.runAction(spaceManDeathAnimation, completion: {() -> Void in
        println("death")
    })

非常感谢大家为解决方案做出的贡献!

我需要 SKAction.repeatAction(stuff, count: 1) 能够正常工作!谢谢! - Phil Hudson

4
你的完成代码没有被调用,因为你的“死亡”操作一直在运行,这意味着它永远不会结束。
你可以使用 setTimeout() 函数来限制"死亡" 操作的时间,以便于完成代码能够被调用。
+ repeatAction:count:

设置重复次数的方法,在完成之前会进行多少次重复:

spaceManDeathAnimation = SKAction.repeatAction(SKAction.animateWithTextures(textures, timePerFrame: 0.15625), count:5)

4

在 Swift 中,您可以使用以下扩展:

extension SKNode
{
    func runAction( action: SKAction!, withKey: String!, optionalCompletion: dispatch_block_t? )
    {
        if let completion = optionalCompletion
        {
            let completionAction = SKAction.runBlock( completion )
            let compositeAction = SKAction.sequence([ action, completionAction ])
            runAction( compositeAction, withKey: withKey )
        }
        else
        {
            runAction( action, withKey: withKey )
        }
    }
}

例如可以这样使用:

myShip.runAction(move,withKey:"swipeMove",optionalCompletion: {
  //Here action is ended..do whatever you want
}

Swift 3:

extension SKNode
{
    func run(action: SKAction!, withKey: String!, optionalCompletion:((Void) -> Void)?) {
        if let completion = optionalCompletion
        {
            let completionAction = SKAction.run(completion)
            let compositeAction = SKAction.sequence([ action, completionAction ])
            run(compositeAction, withKey: withKey )
        }
        else
        {
            run( action, withKey: withKey )
        }
    }

    func actionForKeyIsRunning(key: String) -> Bool {
            return self.action(forKey: key) != nil ? true : false
    }
}

使用方法:

myShip.runAction(action: move, withKey:"swipeMove", optionalCompletion: {
       //Here action is ended..do whatever you want
}

我为两个非常愚蠢的问题道歉:为什么你要给这个第一个操作分配一个 withKey: String! - Confused
1
@Confused 它只是检查当前是否正在运行某个动作。例如,如果要避免旋转被覆盖,可以使用它进行如下操作:if !sprite.actionForKeyIsRunning("rotate") { // do rotation } - Alessandro Ornano
1
当然可以使用它来删除,就像你所写的那样。 - Alessandro Ornano
1
抱歉,我只看到了你的第一条评论。对于你的评论,答案是:因为你可以用键来识别一个动作。 - Alessandro Ornano
@AlessandroOrnano,请在您的actionForKeyIsRunning方法中使用@inline(__always)以获取更好的性能。内联函数将减少类似推送和弹出堆栈等函数带来的开销,代价是增加可执行文件的大小。由于您的方法很小,所以您几乎不会注意到大小的增加,但如果您对其进行测试,您将看到性能的提高。 - Knight0fDragon
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接