Search code examples
xcodeswift3sprite-kit

SpriteKit animate nodes to specific position


I am building my first game with SpriteKit, written in Swift 3.

I have been trying for hours to accomplish this "winning stars effect", but without any acceptable result yet :/

The effect i am looking for is demonstrated in this video: https://youtu.be/9CeK5_G8T9E

It's not a problem adding one or multiple stars; the problem is to make them move in different directions by different paths to the same location, just like it's done in this video example.

Hope for your help to lead me in the right direction.

Any solution, tutorials, examples etc. is more than welcome.

Thanks for your time.


Solution

  • Took a while but here's something:

    import SpriteKit
    
    class GameScene: SKScene {
    
    var sprite = SKSpriteNode()
    
    override func didMove(to view: SKView) {
        
        for _ in 1...15 {
            spawnsprite()
        }
    }
    
    func spawnsprite() {
        
        sprite = SKSpriteNode(color: SKColor.yellow, size: CGSize(width: 50, height: 50))
        sprite.position = CGPoint(x: (-size.width/2)+50, y: (-size.height/2)+50)
        addChild(sprite)
        
        let destination = CGPoint(x: (size.width/2)-50, y: (size.height/2)-50)
        let path = createCurvedPath(from: sprite.position, to: destination, varyingBy: 500)
        
        let squareSpeed = CGFloat(arc4random_uniform(600)) + 200
        let moveAction = SKAction.follow(path, asOffset: false, orientToPath: false, speed: squareSpeed)
        let rotateAction = SKAction.repeatForever(SKAction.rotate(byAngle: 2 * CGFloat.pi, duration: 2))
        sprite.run(SKAction.group([moveAction, rotateAction]))
    }
    
    func createCurvedPath(from start: CGPoint, to destination: CGPoint, varyingBy offset: UInt32) -> CGMutablePath {
        let pathToMove = CGMutablePath()
        pathToMove.move(to: start)
        let controlPoint = CGPoint(x: CGFloat(arc4random_uniform(offset)) - CGFloat(offset/2),
                                   y: CGFloat(arc4random_uniform(offset)) - CGFloat(offset/2))
        pathToMove.addQuadCurve(to: destination, control: controlPoint)
        return pathToMove
    }
    
    override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered
    }
    }
    

    There's a lot that can be done to make this nicer (e.g. subclass SKSpriteNode and make the path that the node follows a property of the sprite itself), but it illustrates the principle.

    It could probably also be done with an SKEmitter.