如何为具有多个子节点的节点创建SpriteKit动画,并将节点的多个部分上的动作设置为一组?
我有以下节点结构:
在下面的例子中,我想让所有孩子弯下腰来拾取种子,为整只鸟做动画。在弯腰的过程中,这只鸟打开它的嘴来吃种子。请注意,喙不是鸟的孩子,它是头节点的孩子。
//body does this action
SKAction* bendDown = [SKAction rotateToAngle:M_PI*0.3 duration:lookUpTiming];
//beak does this action
SKAction* openBeak = [SKAction rotateToAngle:-M_PI*0.175 duration:beakDuration + arc4random()%20/100.0];
//I need both actions to be played together as a group:
SKAction* bendAndOpenBeak = [SKAction group:@[bendDown, openBeak]];
//if I call this, the body will perform both actions.
[self runAction:bendAndOpenBeak completion:^{
}];
这里是我可以在头节点上运行的代码,让它的孩子使用runAction:onChildWithName:
执行操作但是,我需要将其作为一个组与身体一起运行(a父节点的父节点
-(SKAction*)openBeak
{
float angleUp = -M_PI*0.175;
float duration = beakDuration + arc4random()%20/100.0;
SKAction* rotateUp = [SKAction rotateToAngle:angleUp duration:duration];
rotateUp.timingMode = SKActionTimingEaseOut;
SKAction* rotateDown = [SKAction rotateToAngle:-angleUp duration: duration];
rotateUp.timingMode = SKActionTimingEaseOut;
return [SKAction group:@[[SKAction runAction:rotateUp onChildWithName:@"beakUpper"],
[SKAction runAction:rotateDown onChildWithName:@"beakLower"] ]];
}
答案 0 :(得分:2)
[SKAction runAction:onChildWithName:]
具有即时持续时间,因此您的小组操作不会等待其完成。
让组等待所有操作完成的简单方法是向组中添加[SKAction waitForDuration:]
,并使用传递给[SKAction runAction:onChildWithName:]
的操作的duration属性
因此,在您的示例中,所需的代码如下所示
-(SKAction*)openBeak {
float angleUp = -M_PI*0.175;
float duration = beakDuration + arc4random()%20/100.0;
SKAction* rotateUp = [SKAction rotateToAngle:angleUp duration:duration];
rotateUp.timingMode = SKActionTimingEaseOut;
SKAction* waitForRotateUp = [SKAction waitForDuration:rotateUp.duration];
SKAction* rotateDown = [SKAction rotateToAngle:-angleUp duration: duration];
rotateUp.timingMode = SKActionTimingEaseOut;
SKAction* waitForRotateDown = [SKAction waitForDuration:rotateDown.duration];
return [SKAction group:@[[SKAction runAction:rotateUp onChildWithName:@"beakUpper"],
[SKAction runAction:rotateDown onChildWithName:@"beakLower"],
waitForRotateDown, waitForRotateUp]];
}
我已经在上面的示例中使用了SKActions duration属性,即使您明确设置持续时间值,因为此方法可用于精灵动画等操作,其中持续时间未明确设置。
答案 1 :(得分:1)
您不需要使用group
,只需在每个节点上逐个运行它们:
//body does this action
SKAction* bendDown = [SKAction rotateToAngle:M_PI*0.3 duration:lookUpTiming];
//beak does this action
SKAction* openBeak = [SKAction rotateToAngle:-M_PI*0.175 duration:beakDuration + arc4random()%20/100.0];
[bodyNode runAction:bendDown];
[beakNode runAction:openBeak];
答案 2 :(得分:0)
以下是您要求的解决方案。这个答案使用Swift 3。
import SpriteKit
class Scene: SKScene {
// 1
let lookUpTiming = 0.2
let beakDuration = 0.2
// 2
let body = SKNode()
let beak = SKNode()
override func sceneDidLoad() {
// 3
let bendDown = SKAction.run {
let action = SKAction.rotate(toAngle: .pi * 0.3, duration: self.lookUpTiming)
self.body.run(action)
}
// 4
let openBeak = SKAction.run {
let duration = self.beakDuration + Double(arc4random_uniform(20)) / 100
let action = SKAction.rotate(toAngle: -.pi * 0.175, duration: duration)
self.beak.run(action)
}
// 5
let group = SKAction.group([bendDown, openBeak])
// 6
run(group)
}
}
以下是此代码中发生的情况: