Search code examples
swiftpathsprite-kitmove

How to move sprite to center while is in a path and then return to the original path?


I am making a game in which a sprite is rotating around a big circle and I want that when touches began the sprite moves to another circle that is in the center of the screen and now the sprite rotatate around it, and when the touches began occurs again the sprite return to the big circle. In my code the sprite moves to the -sprite.position.x * 2 so that makes that the sprite move to the oposite side of the big circle. How can I solve that?


Solution

  • One of the easiest ways to move an object in a circular path is to

    1. Create a SKNode container
    2. Create a sprite
    3. Add the container to the scene
    4. Add the sprite to the container
    5. Set the sprite's x position to the radius of the circular path
    6. Rotate the container

    If you want to move the sprite to the another circle with a different radius,

    1. change the sprite's x position
    2. move the container's position (optional)

    If you want to change the direction of the rotation,

    1. reverse the container's rotation

    Here's an example:

    // Define circle
    struct Circle {
        var position:CGPoint
        var radius:CGFloat
    }
    
    class GameScene: SKScene {
        // 1. Create container node
        let node = SKNode()
        // 2. Create a sprite
        let sprite = SKSpriteNode(color:SKColor.blueColor(),size:CGSizeMake(10,10))
        var rotation:CGFloat = CGFloat(M_PI)
        var circles:[Circle] = []
    
        override func didMoveToView(view: SKView) {
            scaleMode = .ResizeFill
    
            circles.append(Circle(position: view.center, radius: 80))
            circles.append(Circle(position: view.center, radius: 40))
            // 3. Add the container to the scene
            addChild(node)
    
            // 4. Add the sprite to the container
            node.addChild(sprite)
            // 5. Set the sprite's x position to the radius of the circular path
            if let circle = nextCircle() {
                node.position = circle.position
                sprite.position = CGPoint(x:circle.radius, y:0)
                // 6. Rotate the container
                rotate()
            }
        }
    
        // Rotate the container
        func rotate() {
            let action = SKAction.rotateByAngle(rotation, duration: 4)
            node.runAction(SKAction.repeatActionForever(action),withKey: "rotate")
        }
    
        // 9. Reverse the container's rotation
        func reverse() {
            rotation = -rotation
        }
    
        // Stop rotating the container
        func stopRotation() {
            if node.actionForKey("rotate") != nil {
                node.removeActionForKey("rotate")
            }
        }
    
        // Returns the next circle's parameters and rotates the array
        func nextCircle() -> Circle? {
            guard let circle = circles.first else {
                return nil
            }
            // Move the current circle to the back of the queue
            circles.append(circles.removeAtIndex(0))
            return circle
        }
    
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            /* Change the sprite's x-position  */
            if sprite.actionForKey("move") == nil {
                stopRotation()
                // 7. change the sprite's x position
                // 8. move the container's position (optional)
                if let circle = nextCircle() {
                    let radius = CGPoint(x:circle.radius, y:0)
                    let moveCenter = SKAction.moveTo(circle.position, duration: 3)
                    let move = SKAction.moveTo(radius, duration: 3)
                    let rotate = SKAction.runBlock {
                        self.rotate()
                    }
                    sprite.runAction(SKAction.sequence([move, rotate]), withKey: "move")
                    node.runAction(moveCenter, withKey: "move")
                }
            }
        }
    }