Search code examples
objective-cswiftsprite-kitskspritenodeskshapenode

SKShapeNode Positioning


I'm poking around SpriteKit and encountered some weirdness i.e i'm simply adding rectangular SKShapeNodethat should be fullscreen on iPhone

override func didMoveToView(view: SKView) {
    let _box            = SKShapeNode(rectOfSize: self.frame.size)
    _box.strokeColor    = SKColor.blueColor()
    _box.fillColor      = SKColor.blueColor()
    _box.position       = CGPointMake(200, 200)
    _box.name           = "box"
    self.addChild(_box)

    let _player         = SKShapeNode(circleOfRadius: 50)
    _player.position    = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
    _player.fillColor   = SKColor.redColor()
    _player.strokeColor = SKColor.redColor()
    _player.name        = "player"
    _player.physicsBody = SKPhysicsBody(circleOfRadius: 50)
    _player.physicsBody?.dynamic = true
    _player.physicsBody?.allowsRotation = false
    self.addChild(_player)

    let _ground         = SKShapeNode(rectOfSize: CGSizeMake(self.frame.width, 20))
    _ground.name        = "ground"
    _ground.position    = CGPointMake(0, 0)
    _ground.fillColor   = SKColor.greenColor()
    _ground.strokeColor = SKColor.greenColor()
    _ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.width, 20))
    _ground.physicsBody?.dynamic = false
    self.addChild(_ground)
}

My views are initialised this way override func viewDidLoad() { super.viewDidLoad() }

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
        // Configure the view.
        let skView = self.view as SKView
        skView.showsFPS = true
        skView.showsNodeCount = true

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .AspectFill

        skView.presentScene(scene)
    }

}

The resulting scene looks like so: screenshot

All Nodes are shifted to the left-bottom. Basically left-bottom corner of rectangular shapes is out of bounds (i've checked that by positioning blue shape to (200, 200) instead of (0, 0) - and left-bottome edges were still out of screen frame.

Anchor point for scene is set to (0, 0) so the basically it looks like for me, that it sets position for central point of shape.

What is a best way to define position of left-bottom corner of the Node, instead of mid-point?


Solution

  • If you create a shape using a bezier path or CGPath, you can specify the position of its "anchor point," where the path's origin specifies the bottom/left corner of the path. For example,

        UIBezierPath* bezierPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 0, 50, 50)];
        SKShapeNode *shape = [SKShapeNode node];
        shape.path = bezierPath.CGPath;
        shape.fillColor = [SKColor blueColor];
    

    Also, if your deployment target is iOS 8, you can create your shape node with

        SKShapeNode *shape = [SKShapeNode shapeNodeWithRect:CGRectMake(0, 0, 50, 50)];
        shape.fillColor = [SKColor blueColor];