0

I am trying to write a routine to roll a die. I want the face to change several times before landing on the final number. The code below does not show the die changing faces. I added the sleep statement in hopes that it would give it time to update but it just stays with the initial face until the end and then shows the final face. Is there a statement to add after changing the texture to force the view to update?

func rollDice() {
    var x: Int
    for var i = 0; i < 50; i++
    {
        x = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)

        let texture = dice[0].faces[x]
        let action:SKAction = SKAction.setTexture(texture)

        pieces[3].runAction(action)


        pieces[3].texture = dice[0].faces[x]
        NSThread.sleepForTimeInterval(0.1)
        print(x)
    }
}
Whirlwind
  • 14,286
  • 11
  • 68
  • 157
JeffG
  • 13
  • 3
  • The screen does not draw until sometime after your function exits. You'll need to set your die face, then set a timer to update for the next face later and allow the function to exit. Without doing this, the die will always show the last face you set. – BergQuester Feb 25 '16 at 21:50
  • Why do you put current thread to sleep ? I guess this is the main thread ? App should be responsive as much as possible (as per docs). Are you using SpriteKit ? If so, use SKAction or update: method and its passed curentTime parameter for time related actions. – Whirlwind Feb 25 '16 at 21:51

2 Answers2

0

As has been pointed out in the comments, the screen only redraws on the main thread. Therefore, you could let the dice rolls take place on a background thread, and redraw the screen on the main thread:

func rollDice() {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
        for i in 0..<50 {
            let x = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)

            dispatch_async(dispatch_get_main_queue) {
                let texture = dice[0].faces[x]
                let action:SKAction = SKAction.setTexture(texture)

                pieces[3].runAction(action)

                pieces[3].texture = dice[0].faces[x]
                NSThread.sleepForTimeInterval(0.1)
                print(x)
            }
        }
    }
}
Tim Vermeulen
  • 12,352
  • 9
  • 44
  • 63
0

Thank you for the help. After reading some about Timers, I came up with the following code:

func rollDice() {
    rollCount = 0
    timer = NSTimer.scheduledTimerWithTimeInterval(0.05, target:self, selector: "changeDie", userInfo: nil, repeats: true)
}

func changeDie () {
    x = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
    print(x)
    let texture = dice[0].faces[x]
    let action:SKAction = SKAction.setTexture(texture)
    pieces[3].runAction(action)
    ++rollCount
    if rollCount == 20 {
        timer.invalidate()
    }
}
JeffG
  • 13
  • 3