0

I want to create this effect, that the score is changing with a delay between every number, like the score on the game over screen in Flappy Bird.

In this example, it should start counting when I touch the screen.

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

//    Global declaration of objects
var scoreLabel = SKLabelNode()
var score:Int = 15

override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    scoreLabel = SKLabelNode(fontNamed: "RubberBiscuitBold")
    scoreLabel.fontSize = 50
    scoreLabel.fontColor = SKColor.blackColor()
    scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
    scoreLabel.zPosition = 1000
    self.addChild(scoreLabel)
}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */

    for var i = 0; i <= score; i++ {

        scoreLabel.runAction(SKAction.waitForDuration(1))
        scoreLabel.text = "\(i)"
        print("\(i)")}

}
JAL
  • 41,701
  • 23
  • 172
  • 300
CodeCake
  • 59
  • 7
  • Possible duplicate of [NSTimer - how to delay in Swift](http://stackoverflow.com/questions/27990085/nstimer-how-to-delay-in-swift) – Ross Drew Feb 01 '16 at 11:23
  • well, that NSTimer thing didn't help. It still doesn't give me that effect – CodeCake Feb 01 '16 at 11:31

3 Answers3

1

try something like this:

for var i = 0; i <= 10; i++ {
        let seconds: Double = 0.5
        let count = i
        let delay = seconds * Double(NSEC_PER_SEC)  // nanoseconds per seconds
        let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(i)))

        dispatch_after(dispatchTime, dispatch_get_main_queue(), {
            print("\(count)")
            scoreLabel.text = "\(count)" })
        }
Witterquick
  • 6,048
  • 3
  • 26
  • 50
  • Wow, thanks for your answer, but I'm getting an error on the second line, it says you can't use * for i and Double, because i is an Int – CodeCake Feb 01 '16 at 11:51
  • thanks, that error is solved, but it's not counting up, it starts and stays at 16. Like the console prints "16" every second and doesn't even count up – CodeCake Feb 01 '16 at 11:57
  • Big thanks! But how do I change the delay between the numbers now? Do I just have to change 'i'? – CodeCake Feb 01 '16 at 12:08
  • change seconds to be the delay you want. let seconds: Double = 3.0 will be a 3 seconds delay. and please accept as correct answer if this solved your problem – Witterquick Feb 01 '16 at 12:09
  • That doesn't work :( It messed it all up, when I let seconds be 0.2 or 3.0. I didn't imagine that just a simple delay would be such a complex thing :o – CodeCake Feb 01 '16 at 12:15
  • oh, u want a diffrent delay, but with the same count as before. so again, see edited answer :) – Witterquick Feb 01 '16 at 12:31
  • Unfortunately that doesn't work either, now, there's only a delay at the beginning but not between the numbers. Do you have another idea? :/ – CodeCake Feb 01 '16 at 12:41
  • it was without the part delay * Double(i) check it. it will work – Witterquick Feb 01 '16 at 12:47
  • THANKS, it finally works! sorry for the wait, I was afk, big thanks! :D – CodeCake Feb 01 '16 at 13:08
1

Alternatively, with a recursive function definition it gets a bit more compact (and hopefully usable)

func countUp(start: Int, end: Int, delay: Double) {
    if start <= end {
        let del = delay * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(del))
        dispatch_after(time, dispatch_get_main_queue()) {
            print("\(start)") // Your rendering code here
            countUp(start + 1, end: end, delay: delay)
        }
    } else {
        let del = delay * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(del))
        dispatch_after(time, dispatch_get_main_queue()) {
            print("I'm done!") // Your continuation code here
            // Please not that you should, for clarity and maintenance, wrap your delayed execution code inside a function.....
        }
    }
}
countUp(10, end: 20, delay: 1)
Eppilo
  • 763
  • 6
  • 19
  • Oh thanks! That also works, is there a way to mark both answers as correct? – CodeCake Feb 01 '16 at 13:14
  • I don't think you can. I think that if an answer is useful to you for some reason you can up vote one and mark the other as correct. – Eppilo Feb 01 '16 at 13:18
  • Dou you know how to tell if that counting function is over/done by any chance? If not I'll just create a new question – CodeCake Feb 01 '16 at 21:21
  • 1
    Add an else {} statement aster the if {}. In such statement you can put the code to be executed after the count down has completed. Make sure you delay the code in there too. – Eppilo Feb 02 '16 at 07:00
  • Answer updated. Note that I have copied the code over (bad practice), you can do better than that and wrap the code in charge for delayed execution of a closure inside a function. – Eppilo Feb 02 '16 at 10:38
0

Just an idea here. What if you create an additional node between the pipes that are a bit smaller. Make it so that once they collide it ups your score.

That would also bring you the delay you want.

Wivvle
  • 51
  • 1
  • 7