Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 367
Marcus Toepper Avatar asked Mar 16 '23 23:03

Marcus Toepper


2 Answers

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)
like image 163
ABakerSmith Avatar answered Apr 01 '23 08:04

ABakerSmith


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)
like image 32
jts Avatar answered Apr 01 '23 09:04

jts