caffeine_inquisitor
caffeine_inquisitor

Reputation: 727

SpriteKit positioning and coordinate system

I have a blank SKScene in my project, and I tried to add a box into the scene as follows:

let blueBox = SKSpriteNode(color: UIColor.blueColor(),
                               size: CGSize(width: 100, height: 100))
blueBox.anchorPoint = CGPoint(x: 0, y: 0)
blueBox.position = CGPoint(x: 0, y: 0)
addChild(blueBox)

For some reason the box does not appear on the screen. If my understanding of the positioning coordinates are correct anchorPoint of 0,0 and position of 0,0 means "treat point 0,0 as the bottom left of the blue box". So I expect to see a blue box at the bottom left of the screen. However, if I change the position like so:

blueBox.position = CGPoint(x: 300, y: 0)

Then I can see the blue box (at the bottom, very close to the left edge). It is as if the bottom left coordinate on the screen does not start from x=0, and some value roughly equivalent to 300.

Would anyone be able to share some light? I'm fairly new to SpriteKit, as you can clearly see..

Second question I have is regarding to the bound and frame inside SKScene. I can see that 'self.size.width' is really the same as 'self.frame.size.width'. Similarly, 'self.size.height' is the same as 'self.size.height' (In my simulator, width is 1024, and height is 768. However, if I do self.view.bounds.size.width, then I got 375. Similarly, self.view.bounds.size.height gives me 667. So my question is, how is this 'view' (SKView) being set in my code? I don't have anything that sets it.

It is literally:

class GameScene: SKScene {

    override func didMoveToView(view: SKView) {
      // prints Optional(375.0) Optional(667.0)
      print("\(self.view?.bounds.size.width) \(self.view?.bounds.size.height)")

      // prints 1024.0 768.0
      print("\(self.size.width) \(self.size.height)")
    }
}

Again, thank you very much in advance for your help!

Upvotes: 4

Views: 2476

Answers (2)

Knight0fDragon
Knight0fDragon

Reputation: 16837

The problem with issue 1 is your scaleMode. By default, it is .AspectFill This means that the aspect of the scene is preserved, and the sizes of the screen that are closest together will be where cropping occurs. Your drawing of the box does happen at (0,0), But (0,0) is not the bottom corner of the screen, it is in cropping territory.

It is very important before you start your game to determine the scaleMode you want. You have 4 choices, .AspectFill, .AspectFit, .Fill, and .ResizeFill. I already went over .AspectFill, .AspectFit is the opposite. Best way to describe this is like watching a dvd. The aspect of the movie is different than the aspect of the monitor, so you get black bars. That is what this will do, black bars while preserving the scene aspect. .Fill does not preserve aspect, and what will happen here, is the scene will scale disportionally to the screen, so if your scene is 9:16 and your device is 2:3, you are going to end up with short stumpy versions of what is originally drawn. Finally you have .ResizeFill, and what this does is basically what you are doing now, it resizes the scene to fit the view. You would use this in cases where you want larger screens to see more of the play area then smaller screens.

Now in most cases, you really do want .AspectFill, and you want to design your games to work around the cropping on the sides. What I like to do, is go into the sks file, and change the size there to be that of a 9:16 ratio. This will allow for all phones but the 4s to be handled flawlessly. The ipads and 4s users will need to deal with a little cropping, but that can easily be managed.

One thing I never recommend doing, is what you are doing now, setting a scene to the view's size. You will find yourself coming into issues when you want to make future changes, so I always recommend sticking with the sks file, and if you want the scene to be the view size, use the .ResizeFill scaleMode.

Your second question has already been answered. Scene bounds are not the same as view bounds, you need to visualize the structure like this:

Screen
-View Controller
--View
---Scene

Every one of those elements may end up having their own coordinates/sizes independent of the other depending on how you layout your app.

Upvotes: 1

caffeine_inquisitor
caffeine_inquisitor

Reputation: 727

Ahh... ok... I found the answer to my problem (partly). In my project I still have the GameScene.sks (that was generated by Xcode for new game project).

In my GameViewController, I constructed the GameScene as follows:

GameScene(fileNamed: "GameScene")

If I change it to :

GameScene(size: view.bounds.size)

then everything works ok. The size that was printed (in my didMoveToView) are now:

Optional(375.0) Optional(667.0)
375.0 667.0

which is expected, as I constructed my GameScene with that dimension. My question about the dimension of this 'bound' still remains though. Is it fixed? I'm running my simulator on IPhone 6s...

Upvotes: 3

Related Questions