1

I'm new to SpriteKit and Swift (done a lot in Obj-C in the past for iOS) but I'm struggling on something that should be very basic.. positioning sprites on the screen!

Centering a label on the screens seems easy enough:

myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));

But when I try to put in the Bottom-left or top-right of the screen it isn't visible:

//Bottom-left label
myLabel.horizontalAlignmentMode = .Left
myLabel.position = CGPoint(x: 0.0, y: self.size.height)

or

//Top-right label
myLabel.horizontalAlignmentMode = .Right
myLabel.position = CGPoint(x: self.size.width, y: self.size.height)

This is with a new project, no other code. What am I doing wrong, please?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
FlatDog
  • 2,685
  • 2
  • 16
  • 19

2 Answers2

0

What you have to keep in mind is that a SpriteKit scene by default takes up far more than the screen. Its default size is 1024 by 768 and everything is scaled for universality unless you tell it otherwise. In your view controller you could see how the scene is initialized. You will see that it probably has a statement that says something like

scene.scaleMode = .AspectFill

This is the source of this. Apple in the documentation explains this in a straightforward manner what happens when you use AspectFill scaleMode:

The scaling factor of each dimension is calculated and the larger of the two is chosen. Each axis of the scene is scaled by the same scaling factor. This guarantees that the entire area of the view is filled but may cause parts of the scene to be cropped.

There are other scale Modes to explore, which you can try but Aspect Fill has a large advantage with its universality.

MaxKargin
  • 1,560
  • 11
  • 13
  • Thank you, so how would I position a label (e.g. a game score count) to the top-right of the screen then? – FlatDog Aug 24 '15 at 17:58
  • Honestly, try hard-coding it in. So CGPointMake(700,750) would be somewhere in the top-right. If you test it on different devices you'll notice that it doesn't move :D – MaxKargin Aug 24 '15 at 18:03
  • And if you reallyy need the accuracy between devices then use UIScreen and determine a constant that you could multiply by for each screen size – MaxKargin Aug 24 '15 at 18:06
  • Thanks, I tried CGPointMake(700,750) but it doesn't work when rotating to landscape. I think I need to read up more on this, totally confused! – FlatDog Aug 24 '15 at 18:15
  • Yeah that wouldn't work well, I think for most people, if the devices is allowed rotate, then they track it and readjust their coordinates. Think of the scene as a huge canvas and your phone screen as just a small part of that. If thats not what you're looking for, then just adjust the scene's size property to take the size of the SKView (you'll want to edit the skView's size as well) using UIScreen mainscreen. you could then use self.size normally... – MaxKargin Aug 24 '15 at 18:20
  • theres a few questions of here I think that give a detailed explanation on adjusting the size to the size of the screen – MaxKargin Aug 24 '15 at 18:21
0

You can specify the size of an SKScene when you create it. Typically you pass the size of the containing SKView so it covers the entire view. If the device rotates, your view is resized (if your app allows the new orientation). I'm not sure if the SKScene if resized. But either way, you need to update the position of your scene contents so that for example the label is in the top-right with the new dimensions.

The view controller whose view presents the scene receives the message viewWillTransitionToSize(_ size:,withTransitionCoordinator coordinator:). You can subclass this method to send a message to a custom method of the presenting SKScene that the size is changing. Then, you can simply reposition the node using the new size since self.frame will update.

myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));

Back to the core of the question! How to position a label in the top-right of the scene? Take into account that the scene origin is bottom-left. For SKLabelNode, the center is really in the center. So, offset by half of the label's dimensions.

myLabel.position = CGPoint(x: self.size.width  - myLabel.size.width /2, 
                           y: self.size.height - myLabel.size.height/2)

By the way, I have never seen an iOS game which uses a sprite based engine (such as Sprite Kit or Cocos2d) which supports device rotation/multiple screen sizes when running on the same device (iPhone/iPad).

CloakedEddy
  • 1,965
  • 15
  • 27