Swift | I am trying to rotate a sprite and change the direction of rotation when I click

I want to rotate one sprite indefinitely, and every time I press the button, I want the sprite to rotate in the opposite direction (back and forth from clockwise to counterclockwise, etc.)

Below is the code I have:

http://pastebin.com/Avj8Njwt

class GameScene: SKScene {

    var center = SKSpriteNode()
    var bg = SKSpriteNode()
    var bigCircle = SKSpriteNode()
    let counterClockwise = SKAction.rotateByAngle(CGFloat(3.14), duration:1)
    let clockwise = SKAction.rotateByAngle(CGFloat(-3.14), duration:1)
    var spin = SKAction()


    override func didMoveToView(view: SKView) {

//Background
        var bgTexture = SKTexture(imageNamed: "images/bg.png")
        bg = SKSpriteNode(texture:bgTexture)
        bg.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(center)

//Center Circle
        var bigCircleTexture = SKTexture(imageNamed: "images/bigCircle.png")
        bigCircle = SKSpriteNode(texture:bigCircleTexture)
        bigCircle.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(bigCircle)

//Center Triangle
        var centerTexture = SKTexture(imageNamed: "images/center.png")
        center = SKSpriteNode(texture:centerTexture)
        center.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(center)
        spin = clockwise
        center.runAction(SKAction.repeatActionForever(spin))
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        /* Called when a touch begins */
        if spin == clockwise  {
            spin = counterClockwise

        }

        else {
            spin  = clockwise
        }
        center.runAction(SKAction.repeatActionForever(spin))
}


    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}

      

+3


source to share


4 answers


Your problem is that you are not deleting the old SKAction

one trying to rotate yours SKSpriteNode

. To do this, you need to keep track of how your sprite rotates. If I was going to implement this, I would subclass SKSpriteNode

, for example:

class RotatingSprite: SKSpriteNode {
    // This is used to keep track of which way the sprite is rotating.
    enum Direction {
        case Left, Right

        mutating func inverse() {
            switch self {
                case .Left : self = .Right
                case .Right: self = .Left
            }
        }
    }

    // These names will be the keys used when running an action.
    // This will allow you to stop the rotate-left or rotate-right actions.
    static let rotateLeftName  = "RotateLeftAction"
    static let rotateRightName = "RotateRightAction"

    var rotationDirection: Direction? {
        didSet {
            if let r = rotationDirection {
                switch r {
                    // Checks the sprite isn't already rotating to the left.
                    // If it isn't, make the sprite rotate to the left.
                    case .Left where oldValue != .Left:
                        rotateLeft()
                    case .Right where oldValue != .Right:
                        rotateRight()
                    default:
                        break
                }
            }
        }
    }

    private func rotateLeft() {
        // Remove the action rotating the sprite to the right.
        self.removeActionForKey(RotatingSprite.rotateRightName)
        // And start the action rotating the sprite to the left.
        let rotateAction = SKAction.rotateByAngle(-CGFloat(M_PI), duration: 1.0)
        self.runAction(SKAction.repeatActionForever(rotateAction), withKey: RotatingSprite.rotateLeftName)
    }

    private func rotateRight() {
        self.removeActionForKey(RotatingSprite.rotateLeftName)
        let rotateAction = SKAction.rotateByAngle(CGFloat(M_PI), duration: 1.0)
        self.runAction(SKAction.repeatActionForever(rotateAction), withKey: RotatingSprite.rotateRightName)
    }
}

      

Now you can use RotatingSprite

like this:



class GameScene: SKScene {
    let rotatingSprite = RotatingSprite(texture:bgTexture)

    override func didMoveToView(view: SKView) {
        rotatingSprite.position = CGPoint(x: frame.midX, y: frame.midY)
        self.addChild(rotatingSprite)
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        // If the sprite isn't turning you've got to set it off.
        if rotatingSprite.rotationDirection == nil {
            rotatingSprite.rotationDirection = .Left

        // If it is turning, change its direction.
        } else {
            rotatingSprite.rotationDirection!.inverse()
        }
    }
}

      

Hope it helps!

+1


source


This is very easy to achieve. Try it,

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */

    [sprite removeAllActions];

     SKAction *action;
    if (isClockWise)
    {

        action = [SKAction rotateByAngle:M_PI duration:1];
    }
    else
    {
        action = [SKAction rotateByAngle:-M_PI duration:1];
    }

   isClockWise = !isClockWise;
    [sprite runAction:[SKAction repeatActionForever:action]];

}

      



Where sprite is SKSpriteNode and will initiate isClockWise for yes or no depending on your starting direction.

+1


source


A quick and dirty way to do it:

import SpriteKit

class GameScene: SKScene {

    var center = SKSpriteNode()
    var bg = SKSpriteNode()
    var bigCircle = SKSpriteNode()
    let counterClockwise = SKAction.rotateByAngle(CGFloat(3.14), duration:1)
    let clockwise = SKAction.rotateByAngle(CGFloat(-3.14), duration:1)
    var spin = SKAction()

    // this is used to identify which direction we are going in. When we change it spin is changed as well
    var isClockwise: Bool = true {
        didSet {
            if isClockwise {
                spin = clockwise
            } else {
                spin = counterClockwise
            }
        }
    }

    let actionKey = "spin" // this is used to identify the SKAction

    override func didMoveToView(view: SKView) {
        //Background
        var bgTexture = SKTexture(imageNamed: "images/bg.png")
        bg = SKSpriteNode(texture:bgTexture)
        bg.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(center)

        //Center Circle
        var bigCircleTexture = SKTexture(imageNamed: "images/bigCircle.png")
        bigCircle = SKSpriteNode(texture:bigCircleTexture)
        bigCircle.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(bigCircle)

        //Center Triangle
        var centerTexture = SKTexture(imageNamed: "images/center.png")
        center = SKSpriteNode(texture:centerTexture)
        center.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(center)
        isClockwise = true // set the initial direction to clockwise
        center.runAction(SKAction.repeatActionForever(spin), withKey: actionKey)
    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        // remove the existing spin action
        center.removeActionForKey(actionKey)

        // reset the direction (this will automatically switch the SKAction)
        isClockwise = !isClockwise

        center.runAction(SKAction.repeatActionForever(spin), withKey: actionKey)
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}

      

You need to remove the action before applying the new one - you can selectively remove the action by calling runAction (action :, withKey :). This allows you to remove the same action using the same key. Change logic spin

is in didSet

for isClockwise

var declaration .

0


source


It was as simple as placing center.removeAllActions in each if statement to make sure the sprite is not currently moving when the direction needs to be changed.

0


source







All Articles