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

Posted

技术标签:

【中文标题】iOS7 SpriteKit 如何对两个或多个精灵节点子节点的动画进行分组?【英文标题】:iOS7 SpriteKit how to group animations of two or more sprite node children? 【发布时间】:2014-05-20 01:12:35 【问题描述】:

如何为具有多个子节点的节点创建 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: 执行操作但是,我需要将其作为一个组与主体(父节点的父节点)节点一起运行

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


【问题讨论】:

你需要展示更多才能得到真正的答案 自己是鸟的身体 这个问题你解决了吗? @rptwsthi 我刚刚发布了一个完整的答案。 【参考方案1】:

[SKAction runAction:onChildWithName:] 具有瞬时持续时间,因此您的组操作不会等待其完成。

让组等待所有动作完成的简单方法是在组中添加一个[SKAction waitForDuration:],并使用传递给[SKAction runAction:onChildWithName:]的动作的持续时间属性

所以在您的示例中,所需的代码如下所示

-(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 持续时间属性,即使您明确设置持续时间值,因为这种方法可用于诸如精灵动画之类的动作,其中持续时间没有明确设置。

【讨论】:

【参考方案2】:

您不需要使用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];

【讨论】:

我需要重复序列 3 次,所以如果我并行运行动作,我需要进行各种计算以确保它们的时间同步。【参考方案3】:

这正是您所要求的解决方案。此答案使用 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)
  

以下是这段代码中发生的事情:

    初始化设置 初始化节点 为第一个动画创建一个 SKAction 为第二个动画创建一个 SKAction 创建一组这两个动作 从现场运行小组。即使它们在不同的节点上,两个动画也会同时触发! ?

【讨论】:

以上是关于iOS7 SpriteKit 如何对两个或多个精灵节点子节点的动画进行分组?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS7 SpriteKit 中为不同大小的图像设置动画?

理解 SpriteKit:移动精灵

多个 SKSpriteNode 的 SpriteKit 多个 SKActions - 等待全部完成

在 SpriteKit 项目中使用精灵图集、纹理图集或资产目录

SpriteKit中精灵之间的碰撞

如何向滑动 SpriteKit 的方向投掷精灵