Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift, sprite kit game: Have circle disappear in clockwise manner? On timer?

Alright, so I don't know the name for this but I have a sprite kit game (a runner game) that, when it's game over, is going to have a "save me" button and a timer that runs out accordingly. When the timer runs out, you can no longer click the button and save the character.

I don't want to display this timer in text however- I want a circle that "unwinds itself," if you will, and disappears at the rate that the timer runs out. I.e. when the timer reaches 0, the circle has fully disappeared. The circle disappears degree by degree in a clockwise motion in accordance with the timer.

Here are some pictures to explain what I'm talking about. enter image description here

How would I do this?

like image 840
blue Avatar asked Aug 16 '15 18:08

blue


1 Answers

By changing the path property of an SKShapeNode at a fixed interval, you can create a frame-by-frame animation sequence. To create the animation, set the path property to a sequence of shapes that starts with a circle and ends with nothing. You can use UIBezierPath, a wrapper for CGPath, to create shapes for the animation using the following steps:

  1. Move path's "pen" to the center of the circle
  2. Add an arc to the path with addArcWithCenter from a startAngle to endAngle
  3. Add a line to the path from the point on the circle corresponding to the ending angle to the center
  4. Change the endAngle by a fixed amount
  5. Repeat steps 1-4

Here's an implementation of the above steps:

override func didMove(to:SKView) {

    let circle = SKShapeNode(circleOfRadius: 50)
    circle.fillColor = SKColor.blue
    circle.strokeColor = SKColor.clear
    circle.zRotation = CGFloat.pi / 2
    addChild(circle)

    countdown(circle: circle, steps: 20, duration: 5) {
        print("done")
    }
}

// Creates an animated countdown timer
func countdown(circle:SKShapeNode, steps:Int, duration:TimeInterval, completion:@escaping ()->Void) {
    guard let path = circle.path else {
        return
    }
    let radius = path.boundingBox.width/2
    let timeInterval = duration/TimeInterval(steps)
    let incr = 1 / CGFloat(steps)
    var percent = CGFloat(1.0)

    let animate = SKAction.run {
        percent -= incr
        circle.path = self.circle(radius: radius, percent:percent)
    }
    let wait = SKAction.wait(forDuration:timeInterval)
    let action = SKAction.sequence([wait, animate])

    run(SKAction.repeat(action,count:steps-1)) {
        self.run(SKAction.wait(forDuration:timeInterval)) {
            circle.path = nil
            completion()
        }
    }
}

// Creates a CGPath in the shape of a pie with slices missing
func circle(radius:CGFloat, percent:CGFloat) -> CGPath {
    let start:CGFloat = 0
    let end = CGFloat.pi * 2 * percent
    let center = CGPoint.zero
    let bezierPath = UIBezierPath()
    bezierPath.move(to:center)
    bezierPath.addArc(withCenter:center, radius: radius, startAngle: start, endAngle: end, clockwise: true)
    bezierPath.addLine(to:center)
    return bezierPath.cgPath
}

and a video clip:

enter image description here

like image 185
0x141E Avatar answered Nov 20 '22 05:11

0x141E