1

I have a SKNode which consists of 4 SKSpriteNodesthat make up a square shape (I hope I'm wording it right). Each side of the square has a different color, and I'm trying to rotate the whole square wihout chaning its position. The way I'm trying is always leading it to change its position when it begins the rotation. This is how I have approached it:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var shape = SKNode()

    override func didMoveToView(view: SKView) {

    self.addChild(shape)
    self.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
    self.physicsWorld.contactDelegate = self

    let greenLine = SKSpriteNode(imageNamed: "Green")
    greenLine.position = CGPoint(x: size.width / 2, y: size.height / 2.5)

    let yellowLine = SKSpriteNode(imageNamed: "Yellow")
    yellowLine.position = CGPoint(x: greenLine.position.x - greenLine.frame.width / 2, y: frame.size.height / 2)

    let redLine = SKSpriteNode(imageNamed: "Red")
    redLine.position = CGPoint(x: greenLine.position.x + greenLine.frame.width / 2, y: frame.size.height / 2)
    let blueLine = SKSpriteNode(imageNamed: "Blue")
    blueLine.position = CGPoint(x: frame.size.width / 2, y: redLine.position.y + redLine.frame.height / 2.3)

    shape.addChild(greenLine)
    shape.addChild(yellowLine)
    shape.addChild(redLine)
    shape.addChild(blueLine)

    let rotateAction = SKAction.rotateByAngle(CGFloat(M_PI_4) * 2, duration: 5)
    shape.runAction(rotateAction)
}

I tried zRotation as well, but that didn't work at all. When rotation happens with an SKAction, it takes the whole shape to the left while rotating, instead of staying at the same place.

Edit

Code:

 var shape = SKNode()

override func didMoveToView(view: SKView) {

    self.addChild(shape)
    self.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
    self.physicsWorld.contactDelegate = self

    backgroundColor = UIColor.whiteColor()

    let greenLine = SKSpriteNode(imageNamed: "Green")
    greenLine.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2.5)

    let yellowLine = SKSpriteNode(imageNamed: "Yellow")
    yellowLine.position = CGPoint(x: greenLine.position.x - greenLine.frame.width / 2, y: frame.size.height / 2)

    let redLine = SKSpriteNode(imageNamed: "Red")
    redLine.position = CGPoint(x: greenLine.position.x + greenLine.frame.width / 2, y: frame.size.height / 2)

    let blueLine = SKSpriteNode(imageNamed: "Blue")
    blueLine.position = CGPoint(x: frame.size.width / 2, y: redLine.position.y + redLine.frame.height / 2.3)

    shape.position = CGPoint(x: 0, y: 0)
    shape.addChild(greenLine)
    shape.addChild(yellowLine)
    shape.addChild(redLine)
    shape.addChild(blueLine)

    let center = SKSpriteNode(color: .redColor(), size: CGSize(width: 50, height: 50))
    center.position = CGPoint(x: frame.midX, y: frame.midY)
    shape.addChild(center)

    let rotateAction = SKAction.rotateByAngle(CGFloat(M_PI_4) * 2, duration: 30)
    shape.runAction(rotateAction)


}
Sharukh
  • 199
  • 1
  • 1
  • 12

1 Answers1

2

You probably don't understand the difference between different coordinate systems. You are adding a shape node to the scene. So when you set the position of the shape you have to work in scene's coordinate system. Same logic applies to the other nodes (lines). Here, you are adding them to the shape, which means you have to "think" in shape's coordinate system. Take a look a this example:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var shape = SKNode()

    override func didMoveToView(view: SKView) {

        self.addChild(shape)
        self.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
        self.physicsWorld.contactDelegate = self

        let greenLine = SKSpriteNode(color: .greenColor(), size: CGSize(width: 50, height: 50))
        greenLine.position = CGPoint(x: -30, y: 30)

        let yellowLine =  SKSpriteNode(color: .yellowColor(), size: CGSize(width: 50, height: 50))
        yellowLine.position = CGPoint(x: 30, y: 30)

        let redLine = SKSpriteNode(color: .redColor(), size: CGSize(width: 50, height: 50))
        redLine.position = CGPoint(x: 30, y: -30 )
        let blueLine =  SKSpriteNode(color: .blueColor(), size: CGSize(width: 50, height: 50))
        blueLine.position = CGPoint(x:-30, y:-30)

        shape.position = CGPoint(x: frame.midX, y: frame.midY)
        shape.addChild(greenLine)
        shape.addChild(yellowLine)
        shape.addChild(redLine)
        shape.addChild(blueLine)

        let center = SKSpriteNode(color: .redColor(), size: CGSize(width: 5, height: 5))

        shape.addChild(center)

        let rotateAction = SKAction.rotateByAngle(CGFloat(2 * M_PI), duration: 5)
        shape.runAction(rotateAction)

    }
}

The result:

rotating

Note the center node. That is the actual position of the shape node. And that is the point around other nodes are being rotated.

Whirlwind
  • 14,286
  • 11
  • 68
  • 157
  • I understand most of what you said except I didn't think about scene's coordinate system. It makes perfect sense on how you explained and I totally understand it, but my problem is with the line `shape.position = CGPoint(x: frame.midX y: frame.midY)`. I tried this before and did again, and when I run my project with that line, it takes `shape` to the top right corner and startes rotating outside the scene. – Sharukh Mar 23 '16 at 22:01
  • Could it be because of how I'm positioning the `lines`? – Sharukh Mar 23 '16 at 22:07
  • @Sharukh Yeah, it is based on how you positioning the children of the shape node. As I said, don't forget that lines are positioned in shape's coordinate system. Also, to find out shape's node position, just add a little dot to it, like I did with center node. Place it at CGPoint(0,0) and you will se where the shape node is placed. – Whirlwind Mar 23 '16 at 22:18
  • I'm still a little confused how to resolve this issue. I have updated my question with new code lines that I have, and upon running, `shape` rotates around the left bottom corner of the screen, at (0,0). – Sharukh Mar 24 '16 at 00:03
  • @Sharukh Just position your nodes differently. Have you put a simple dot to show you where is the "center" of the shape container? Then use that dot as (0,0) and position your nodes relative based on it. Not sure how to explain you better. Right now, it seems that your nodes are positioned like you would position them if they were added as children to the scene directly... – Whirlwind Mar 24 '16 at 00:07
  • When you place shape container at position (frame.midX, frame.midY) it will be positioned at the center of the screen (scene). Like in my example. Then, if you add a line to the shape node at position CGPoint( x:0, y:0), the line will be placed right where the shape is placed. But for example, if you add a line to the scene at position (0,0) it will be placed in the bottom left corner of the screen. So when you add a line to the shape container, it will be positioned relatively to the shape node, where (0,0) is the shape's position. – Whirlwind Mar 24 '16 at 00:15
  • Hey yeah sorry. I understood when you explained again about placing a dot. I was implementing it and got it working and now it makes perfect sense. Once I say `shape.position`, that becomes the origin and I have to then position the childs accordingly. Thank You, appreciate it for the help :) – Sharukh Mar 24 '16 at 00:30
  • Yup, I don't have programming background, so it takes me forever to understand even little concepts like these lol – Sharukh Mar 24 '16 at 00:37