SKAction排序和分组动画

时间:2017-05-04 21:07:54

标签: swift sprite-kit skspritenode

我为游戏做了一些死亡动画,想要求一些帮助。我希望我的怪物能够在一阵烟雾中消失,但不会在它的身体上产生斜线效果。

我想要使用3个动画:

weaponSlash - 吸引怪物的一条线。看起来你用剑砍了他一刀。

冒烟 - 一股烟雾慢慢膨胀

monsterFalling - 怪物倒退,吓了一跳

我想要做的是按此顺序播放:

  1. 同时,斜线出现&怪物开始倒退
  2. 上述动画大约0.25秒,我希望云开始出现
  3. 当云即将结束时(也许可能在1秒后)我希望怪物消失
  4. 移除烟雾,怪物,剑等,并将一些硬币放在地上
  5. 我这样开始,作为一种有效的测试:(暂时忽略上述时间)

     //Cancel any current actions, like a monster attacking
     monster.removeAllActions()
    
     //since you can't play 3 animations on one node at the same time, you have to create 3 separate nodes for everything                          
     let slash = SKSpriteNode()
     let cloud = SKSpriteNode()
     cloud.size = monster.size
     slash.size = monster.size
     monster.addChild(cloud)
     monster.addChild(slash)
    
    
     //Start the slash animation
     slash.run(self.player.currentlyEquippedWeapon.attackAnimation())
    
     //Start the cloud animation (how I get it is elsewhere and not relevant)
     cloud.run(cloudAnimation)
    
    //Run the monster death animation, followed by the cleanup/coin dropping                   
    monster.run(SKAction.sequence([monster.deathAnimation(), SKAction.wait(forDuration: 1), postDeathActions]))
    

    上面的变量PostDeathActions简单地移除了怪物节点并动画了一些硬币掉落。

    我需要一些帮助

    所以上面的代码并没有那么好用,因为动画都是彼此独立运行的。基于此,你可以看到无论是否斜线/云完成,怪物将运行两个动作:他后退,然后清理,这只是移除怪物并产生硬币。正如你所看到的那样,我试图通过添加1s延迟来延迟这一点,但这有点像黑客,因为我可能有更快/更慢的不同怪物或攻击等。在我消灭怪物之前,我宁愿保证一切都结束了。

    我尝试将其分组为SKAction.Run,​​如下所示:

    let preDeath = SKAction.run {
     [unowned self] in
       monster.run(monster.deathAnimation() 
       slash.run(self.player.currentlyEquippedWeapon.attackAnimation())
       cloud.run(cloudAnimation)
     }
    

    但是这会同时运行所有内容。

    我想要做的是像这样排序(伪代码):

    让preDeathAnimations = SKAction.Group([斜杠,云,monsterDeathAnimation]) ])

    SKAction.sequence([preDeathAnimations,postDeathActions])

    因此,在运行清理之前,它将运行所有3个。

    有没有办法做这样的事情?我知道Sequnce / Group需要针对SKNode运行,但我没有3个单独的。

    感谢您抽出时间阅读本文以及您可以提供的任何建议!

1 个答案:

答案 0 :(得分:1)

这是我的一个想法,但您可以使用线程+状态+ onCompletion块来从中获取数学。我没有完全测试它,但这个一般概念工作:

let slash = SKAction.fadeIn(withDuration: 0.5)

let fall = SKAction.fadeOut(withDuration: 0.25)

let puff = SKAction.fadeIn(withDuration: 0.1)

// Put in ALL of the actions from ALL parties that you want to happen prior to puff:
func findLongestTime(from actions: [SKAction]) -> TimeInterval {

  var longestTime = TimeInterval(0)

  for action in actions {
    if action.duration > longestTime { longestTime = action.duration }
  }

  // Note, if you put a sequence into this function I don't know if it will work right..
  // Might need another func like `findDurationOfSequence(_ sequence: SKAction) -> TimeInterval
  return longestTime
}

// Note, if you have the monster doing more than falling prior to puff, then you will
// need to subtract those as well:
let monsterActionsPriorToPuff = [fall]

// Add the duration of all monster animations prior to puff:
var MAPTP_duration = TimeInterval(0)
for action in monsterActionsPriorToPuff {
  MAPTP_duration += action.duration
}

// Calculate our final wait time, with no negative numbers:
  var waitTime = findLongestTime(from: [slash, fall]) - MAPTP_duration
if waitTime < 0 { waitTime = 0 }
let wait = SKAction.wait(forDuration: waitTime)

// Our monster sequence (I forgot to add the disappear, just add after puff)
let monsterSequence = SKAction.sequence([fall, wait, puff])

// Player slashes:
SKSpriteNode().run(slash)

// Monster will wait 0.25 seconds after falling,
// for slash to finish before puffing:
SKSpriteNode().run(monsterSequence)

我知道如果这个想法不起作用我可以尝试更新它。