John
John

Reputation: 389

Rotate SKSpritenode by a changing number of degrees

How can I define an SKAction, and then update the number of degrees my node will rotate? I am trying to define it with variables, but when I update the variable values the action doesn't update.

var degreesToRotate = 4
var direction = 1

let action = SKAction.rotate(byAngle: CGFloat(degreesToRotate * direction), duration: TimeInterval(2))
            charector.run(SKAction.repeatForever(action))

direction = -1

Upvotes: 3

Views: 1574

Answers (1)

Whirlwind
Whirlwind

Reputation: 13675

import SpriteKit
import GameplayKit

//Extensions borrowed from here : http://stackoverflow.com/a/29179878/3402095

extension Int {
    var degreesToRadians: Double { return Double(self) * .pi / 180 }
    var radiansToDegrees: Double { return Double(self) * 180 / .pi }
}
extension FloatingPoint {
    var degreesToRadians: Self { return self * .pi / 180 }
    var radiansToDegrees: Self { return self * 180 / .pi }
}

let kActionKey = "rotate"

class GameScene:SKScene {

    let purpleCube = SKSpriteNode(color: .purple, size: CGSize(width: 150, height: 150))
    let yellowCube = SKSpriteNode(color: .yellow, size: CGSize(width: 150, height: 150))

    override func didMove(to view: SKView) {


        addChild(purpleCube)
        purpleCube.position.y = purpleCube.size.height
        purpleCube.name = "purple"


        addChild(yellowCube)
        yellowCube.position.y = -yellowCube.size.height
        yellowCube.name = "yellow"

        let rotate = SKAction.rotate(byAngle: CGFloat(-M_PI * 2.0), duration: 5)
        let loop = SKAction.repeatForever(rotate)
        purpleCube.run(loop, withKey: kActionKey)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        super.touchesBegan(touches, with: event)


        if let touch = touches.first {

            let location = touch.location(in: self)

            if let cube = atPoint(location) as? SKSpriteNode {

                if let name = cube.name {

                    switch name {

                    case "purple":

                        if let action = purpleCube.action(forKey: kActionKey){

                            purpleCube.run(action.reversed(), withKey: kActionKey)
                        }


                    case "yellow":

                        if action(forKey: "rotating") == nil{
                           yellowCube.run(SKAction.rotate(byAngle: CGFloat(4.degreesToRadians), duration: 0.1), withKey: kActionKey)
                        }



                    default:
                        break
                    }
                }

            }
        }

    }
}

In this example, there are two nodes that have been rotated in a two different ways. Purple node is rotated constantly at certain speed in clockwise direction. To achieve this, I've created an action that rotates a sprite by 360 degrees... That would be one revolution, which will be repeated forever, thus the sprite will be rotated forever.

About the yellow node...It will be rotated by 4 degrees every time you tap on it. Currently you have to wait that sprite stop rotating so you can rotate it more. This is optional of course, I just wanted to show you the usefulness of action keys.

Rotation Direction

Since in SpriteKit 0 degrees specifies positive x-axis and a positive angle is in counterclockwise direction, I rotated purple cube by -360 degrees, which rotates the sprite in clockwise direction. To find out more about SpriteKit coordinate system, read this documentation section.

Radians Vs Degrees

As you can see, I am talking in degrees, rather than in radians... That is because it would be really hard to say, I rotated the sprite by 6.2831853072 radians :) That is why I used extensions which does conversion from degrees to radians and vice-versa. You might use this often so I added them for you.

Upvotes: 4

Related Questions