iOS7 SpriteKit如何分组两个或多个精灵节点子节点的动画?

时间:2014-04-07 16:49:34

标签: animation ios7 sprite-kit skaction

如何为具有多个子节点的节点创建SpriteKit动画,并将节点的多个部分上的动作设置为一组?

我有以下节点结构:

  • Bird有身体,尾巴,头等的儿童节点
  • 头部有上喙,下喙等的子节点

在下面的例子中,我想让所有孩子弯下腰来拾取种子,为整只鸟做动画。在弯腰的过程中,这只鸟打开它的嘴来吃种子。请注意,喙不是鸟的孩子,它是头节点的孩子。

//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"] ]];

}

3 个答案:

答案 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)
  }
}

以下是此代码中发生的情况:

  1. 初始化设置
  2. 初始化节点
  3. 为第一个动画创建SKAction
  4. 为第二个动画创建SKAction
  5. 创建一组这两个操作
  6. 从场景中运行组。即使它们位于不同的节点上,两个动画也会一起发射!