Marcus Toepper
Marcus Toepper

Reputation: 2423

Moving a SKSpriteNode in a downward loop, using Swift

Using Swift and SpriteKit, I'd like to move a SKSpritenode in a spiral pattern, but didn't find the right resources to get me started. To be more precise, I'd like to move a sprite node in a downward loop. I've checked a sequence of SKActions, but as they are not executed parallel, a circular movement combined with move-to will not work. I'd be glad for any hints, tutorials or snippets to set me on the right track.

Thanx in advance, Marcus

Upvotes: 4

Views: 968

Answers (2)

jts
jts

Reputation: 33

While the above mentioned solution is brilliantly thought of, there is a much easier way.

  1. Add a spinnerNode, and repetitively spin it using rotateBy
  2. Add your sprite as a child to the spinnerNode (your sprite will by default rotate with the spinnerNode)
  3. Move your spriteNode (using moveTo) to the centre of the wheelNode (your sprite will appear traveling in a spiral path to the center)

Upvotes: 2

ABakerSmith
ABakerSmith

Reputation: 22939

I've put together some sample code which you can adapt for your purposes. I've based the code off the equation for an Archimedean Spiral:

r = a + bθ

Where a is the starting radius; b is the radius the spiral will increase by per revolution and θ is the current angle.

A spiral is basically a glorified circle (IMO), so to move your node in a spiral you need to be able to calculate point on a circle using an angle, radius and center point:

func pointOnCircle(#angle: CGFloat, #radius: CGFloat, #center: CGPoint) -> CGPoint {
    return CGPoint(x: center.x + radius * cos(angle),
                   y: center.y + radius * sin(angle))
}

Next, extend SKAction so you can easily create a spiral action:

extension SKAction {
    static func spiral(#startRadius: CGFloat, endRadius: CGFloat, angle 
         totalAngle: CGFloat, centerPoint: CGPoint, duration: NSTimeInterval) -> SKAction {

        // The distance the node will travel away from/towards the 
        // center point, per revolution.
        let radiusPerRevolution = (endRadius - startRadius) / totalAngle

        let action = SKAction.customActionWithDuration(duration) { node, time in
            // The current angle the node is at.
            let θ = totalAngle * time / CGFloat(duration)

            // The equation, r = a + bθ
            let radius = startRadius + radiusPerRevolution * θ

            node.position = pointOnCircle(angle: θ, radius: radius, center: centerPoint)
        }

        return action
    }
}

Finally, an example of use. In didMoveToView:

let node = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 10, height: 10))
node.position = CGPoint(x: size.width / 2, y: size.height / 2)
addChild(node)

let spiral = SKAction.spiral(startRadius: size.width / 2,
                             endRadius: 0,
                             angle: CGFloat(M_PI) * 2,
                             centerPoint: node.position,
                             duration: 5.0)

node.runAction(spiral)

Upvotes: 5

Related Questions