3

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
Whirlwind
  • 14,286
  • 11
  • 68
  • 157
John
  • 371
  • 1
  • 3
  • 11
  • 1
    You should use `SKAction.rotate(byAngle` with radians, not degrees, take a look [here](https://developer.apple.com/reference/spritekit/skaction/1417805-rotate) – Alessandro Ornano Jan 28 '17 at 16:42
  • It gives me an "expected separator" error: let action = SKAction.rotate(byAngle radians: CGFloat(degreesToRotate * direction), duration: TimeInterval(2)) – John Jan 28 '17 at 16:54
  • @John This is how you call that method : `let action = SKAction.rotate(byAngle: CGFloat(M_PI), duration: 1)` , don't just copy and paste the code from docs. – Whirlwind Jan 28 '17 at 17:19
  • How can I update the angle the node should rotate? – John Jan 28 '17 at 17:34
  • @John, try to explain what kind of rotation you are trying to achieve ? You want a loop that rotates the node infinitely in one direction ? or you want to rotate the node only once by certain amount of degrees? Or something else? – Whirlwind Jan 28 '17 at 17:37
  • @Whirlwind I want to start by rotating the node 4 degrees, and at a later time change it to -4 degrees based on user interaction. I set the variable "direction" to 1 at the beginning, and change it to -1 later. I am using this: SKAction.rotate(byAngle: CGFloat(4 * direction). But the action won't look at the updated value of "direction" – John Jan 28 '17 at 17:40
  • @John So eg. on each tap you want to rotate a sprite by 4 degrees and you want that animated ( where an animation duration is 1 second) ? – Whirlwind Jan 28 '17 at 17:46
  • @Whirlwind My cube will consistently rotate 4 degrees until the user taps the right side of the screen- then it will rotate toward that direction (-4 degrees) – John Jan 28 '17 at 17:48
  • @John Okay that is not a problem, but I think you are not explaining this correctly, or I am not understanding what you are trying to achieve. I will write an example for you anyways to show you how to rotate node in different situations. I don't get why do you mentioning those "4 degrees" if a cube rotates constantly ? If it rotates constantly, then speed is what matters (and direction), not the amount of degrees you are mentioning... – Whirlwind Jan 28 '17 at 17:52
  • I see, I thought the number of degrees affected the speed – John Jan 28 '17 at 17:56
  • It will, but there is a duration parameter as well. I will write an example for you to show how to do this. – Whirlwind Jan 28 '17 at 17:57
  • @Whirlwind let me know when you have that example ready – John Jan 28 '17 at 18:38
  • @John I've posted an answer. You can copy and paste the code to see how it works... Currently I am just toggling direction on purple sprite. In your case you may want to add a instance property on a scene (or anywhere you feel convenient) and based on that , to change the rotating direction – Whirlwind Jan 28 '17 at 18:42
  • Thanks! I'll have a look – John Jan 28 '17 at 18:43

1 Answers1

4
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.

Whirlwind
  • 14,286
  • 11
  • 68
  • 157