How to rotate sprite in sprite kit with swift

11,210

OK, take three. I'm not 100% sure about the specifics of when the rotation should end etc. but all the pieces should be in place with the below code. It will:

  • start rotation clockwise or counterclockwise based on the position of the first touch
  • stop the rotation if the user touches for the same direction again
  • switch the rotation if the user touches on the other half of the screen

      import SpriteKit  
    
      enum rotationDirection{
           case clockwise
           case counterClockwise
           case none
       } 
    
      class GameScene: SKScene {
        var currentRotationDirection = rotationDirection.none
        let sprite = SKSpriteNode(color: UIColor.yellowColor(), size: CGSizeMake(100, 100))
    
        override func didMoveToView(view: SKView) {
          sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
          sprite.physicsBody.affectedByGravity = false
          sprite.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
          self.addChild(sprite)
        }
    
        override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
          let touch : UITouch = touches.anyObject() as UITouch
          let touchPosition = touch.locationInNode(self)
          let newRotationDirection : rotationDirection = touchPosition.x < CGRectGetMidX(self.frame) ? .clockwise : .counterClockwise
    
          if currentRotationDirection != newRotationDirection && currentRotationDirection != .none{
            reverseRotation()
            currentRotationDirection = newRotationDirection
          } else if currentRotationDirection == newRotationDirection{
            stopRotation()
            currentRotationDirection = .none
          } else if (currentRotationDirection == .none){
          setupRotationWith(direction: newRotationDirection)
          currentRotationDirection = newRotationDirection
          }
        }
    
        func reverseRotation(){
          let oldRotateAction = sprite.actionForKey("rotate")
          let newRotateAction = SKAction.reversedAction(oldRotateAction)
          sprite.runAction(newRotateAction(), withKey: "rotate")
        }
    
        func stopRotation(){
          sprite.removeActionForKey("rotate")
        }
    
        func setupRotationWith(#direction: rotationDirection){
          let angle : Float = (direction == .clockwise) ? Float(M_PI) : -Float(M_PI)
          let rotate = SKAction.rotateByAngle(angle, duration: 1)
          let repeatAction = SKAction.repeatActionForever(rotate)
          sprite.runAction(repeatAction, withKey: "rotate")
        }
      }
    

Edit: Changed example to cater the specific needs in the question. Something odd with the code formatting not quite sure what's going on there.

Share:
11,210
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    Hi my problem is regarding the rotation of two sprites. When I touch the right half of the screen the rotation starts and moving sprite2 and sprite3. If I touch the left half of the screen the rotation stops because velocity-velocity = 0. If I touch the left half again the rotation begins.

    However, if I touch the half of the screen corresponding with the current rotational-direction the velocity is duplicated. I want to be able to change the direction of the rotation, but for the speed to remain constant.

    Video demonstrating the problem: http://youtu.be/HxLwl1QZiNM

    import SpriteKit
    
    class GameScene: SKScene {
        let sprite = SKSpriteNode(imageNamed:"bWhite")
        let sprite2 = SKSpriteNode(imageNamed:"bBlue")
        let sprite3 = SKSpriteNode(imageNamed:"bRed")
        let circle = SKSpriteNode(imageNamed:"bCircle")       
    
        override func didMoveToView(view: SKView) {
            /* Setup your scene here */
            backColor = SKColor(red: 0, green: 0, blue: 0, alpha: 1)
            self.backgroundColor = backColor
    
            sprite.setScale(1.25)
            sprite2.setScale(1)
            sprite3.setScale(1)
            sprite.position = CGPointMake(self.frame.size.width/2, (self.frame.size.height/2)-200);
            circle.position = CGPointMake(self.frame.size.width/2, (self.frame.size.height/2)-200);
            sprite3.zRotation = 172.77
            sprite2.anchorPoint = CGPointMake(-1.10, 0.5);
            sprite3.anchorPoint = CGPointMake(-1.10, 0.5);
    
            self.addChild(sprite)
            self.addChild(circle)
            sprite.addChild(sprite2)
            sprite.addChild(sprite3)
        }
    
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
            /* Called when a touch begins */
            for touch: AnyObject in touches {
                let location = touch.locationInNode(self)
    
                let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)
                let action2 = SKAction.rotateByAngle(CGFloat(-M_PI), duration:1)
    
                if (location.x > self.frame.size.width / 2)
                {
                    sprite2.runAction(SKAction.repeatActionForever(action2))
                    sprite3.runAction(SKAction.repeatActionForever(action2))
                } else {
                    sprite2.runAction(SKAction.repeatActionForever(action))
                    sprite3.runAction(SKAction.repeatActionForever(action))
                }     
            }
        }
    
  • Admin
    Admin almost 10 years
    yeah it works you are the best, but I want to move while I'm touching left half of screen rotate to left, If I don't touch stop and if I touch right half of screen rotate to right
  • Admin
    Admin almost 10 years
    If i touch left half of screen rotate to left if stop touching left stop de rotation, no move .If i touch right half of screen rotate to right if stop touching right stop de rotation, no move.
  • T. Benjamin Larsen
    T. Benjamin Larsen almost 10 years
    Not quite sure what you are trying to achieve: Do you want the rotation to STOP if you touch a second time on the same half of the screen? Or do you want the rotation to stop when touching the opposite side?
  • Admin
    Admin almost 10 years
    the rotation should end If I lift my finger from the screen
  • T. Benjamin Larsen
    T. Benjamin Larsen almost 10 years
    OK, then you need to remove the else if currentRotationDirection == newRotationDirection and implement currentRotationDirection = .none and call the stopRotation() function in touchesEnded