1

I have SKLabelNode representing current score, which I'm trying to animate with growing and shrinking sequence, whenever score value hits some particular number(e.g. 10, 20, ...). Problem is that animation itself has some sort of delay inbetween and takes far more time than duration I've set. Basically it grows, then it waits and after while finally shrinks back.

Here's my code:

override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        ...
        //skactions setting
        growAction = SKAction.scaleBy(1.2, duration: 0.4)
        shrinkAction = SKAction.scaleBy(0.8333, duration: 0.4)
        growAndShrink = SKAction.sequence([growAction, shrinkAction])
        ...
}


override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */

        if (score % 10) == 0 && score != 0 && gameState == GameState.Play {
            scoreLabel.runAction(growAndShrink)
        }       
}

I though update func is the right one to use for that, or is it?

Adam Bardon
  • 3,829
  • 7
  • 38
  • 73
  • 1
    as long as the conditions remain true, which i assume will be the case for at least a couple frames, you will run the sequence. So you have several sequences running simultaneously, overwriting each other's scale modifications – CodeSmile Jan 22 '15 at 08:50
  • true, so I need to add some sort of flag for that condition to ensure that only one sequence at a time can be run, or is there better solution? – Adam Bardon Jan 22 '15 at 08:55
  • 1
    yes, or even better: run this check in the method where the score variable is changed – CodeSmile Jan 22 '15 at 09:45
  • finaly I was able to try it, and indeed running it at the same place as when score is changed is the best and easiest solution – Adam Bardon Jan 24 '15 at 18:33

2 Answers2

1

You can use the completion: argument here to make a call to the function that checks, whether the action should be re-run, e.g.

scoreLabel.runAction(growAndShrink, completion: { self.runAgain() })

runAgain would then contain your logic for checking and re-running the action. Basically you can combine both:

func runGrowAndShrinkAction()
{
    if (conditions)
    {
        scoreLabel.runAction(growAndShrink, completion: { self.runGrowAndShrinkAction() })
    }
}

Sidenote: if you use runBlock in your sequence, please consider, that it is called asynchronously. That is, the execution of completion: does not wait for the runBlock being finished.

Update: another option is to use SKAction.repeatActionForever() and if the conditions in your update method change, you can remove the action with removeActionForKey().

Sebastian
  • 8,046
  • 2
  • 34
  • 58
1

You can create a didSet property observer on score to update the score label dynamically and perform the animation.

var score : Int = 0 {
    didSet
    {
        scoreLabel.text = "Score : \(score)"

        if (score % 10 == 0 && score != 0 && gameState == GameState.Play)
        {
            animateScore()
        }
    }
}

func animateScore()
{
    scoreLabel.removeAllActions()
    scoreLabel.text = "Score : \(score)"
    let growAction = SKAction.scaleBy(1.2, duration: 0.4)
    let shrinkAction = SKAction.scaleBy(0.8333, duration: 0.4)
    let growAndShrink = SKAction.sequence([growAction, shrinkAction])
    scoreLabel.runAction(SKAction.repeatAction(growAndShrink, count: 2))
}
rakeshbs
  • 24,392
  • 7
  • 73
  • 63