I apologize in advance because of huge post, but everybody who ever tried to make some kind of universal app knows that this is pretty problematic stuff, so please be easy on me...
The goal
What I am trying to achieve (shown on image above) is to use @2x assets on both iPhone 5 and 6, and maintain same look of an app. And if possible, to do all that without manually calculating scale and position properties of nodes based on detected device... So in short, how to achieve that app automatically constrain proportions of, and between elements (and scene)? Also I would like to have same look of an app on iPhone 6+ using @3x assets, but because of simplicity I've concentrated only on iPhone 5 an 6.
What I have found on the web is that some people saying that this (downsampling) is done automatically by iOS, for example they suggest this:
"Make @2x assets at the size for iPhone 6, and then iOS will do downscaling automatically for iPhone 5".
But that's obviously not true when it comes to Spritekit scene, or I am missing something.
The problem
Even though iPhone 6 and iPhone 5 have same aspect ratio and same PPI, using the same asset won't look the same compared to the scene size (look menu sprite on 1st and 2nd image compared to the scene size) because PPI are related to pixel density, and iPhone 6 has more space (bigger diagonal, more inches) which means it has more pixels than iPhone 5. And this is where my problem comes from and I don't know what would be an efficient way to handle it.
What I have done so far
The second image is not a problem for GUI, but for a gameplay, in my case it is, because I want same look and feel on different devices. Just look first and third image.
Thanks to Skyler Lauren's suggestion I've managed to have same look of an app across all iPhone 5 devices either on 7.1 or 8.1 systems as well as on iPhone 6. So now, the problem is how to adapt this code to works with iPhone 6+ using @3x textures, as well as on iPhone 4s. Here is the solution for iPhone 5 and 6:
View controller.m
GameScene *scene = [GameScene sceneWithSize:CGSizeMake(375,677)];//fixed instead of view.bounds.size
scene.scaleMode = SKSceneScaleModeAspectFill;
So the scene always has fixed size at iPhone 6 dimensions and view size is changing according to device. I am using assets catalog for launch images and not xib file. Images are sized at recommended size - 640x960px for 4s, 640x1136px for 5, 750x1334px for 6 and 1242x2208 for 6+ model. Assets are sized for iPhone 6 so for that model there is no scaling at all.
Related to 4s model, when I am using this method described above, there are two black bars from each side...
So far I've tested this only on simulator and iPhone 6 device (what I see looks like on first image either on device or simulator).
Question
For now as I said everything works on iPhone 4s(with two black bars because of different aspect ratios), 5, 6 using @2x assets, but how make everything to work with iPhone 6+ using @3x assets ? If I use 375x667 dimensions for the scene, then everything is positioned properly and has good proportions, but quality suffers (because of upscaling @2x)
Uniform GUI and Game Play
As far as I can tell the best way to handle a uniform GUI and game play is to set your scene size (regardless of device) and let SpriteKit scale from there.
GameScene *scene = [GameScene sceneWithSize:CGSizeMake(375,677)];//fixed instead of view.bounds.size
scene.scaleMode = SKSceneScaleModeAspectFill;
That is the points for an iPhone 6. Because SpriteKit works in points but devices display in pixels the scene size will be 750px x 1354px pixels for @2x devices and 1125px x 2031px for the iPhone 6+ (the device in pixels is actual 1080 x 1920).
How does this work with assets?
Well it works rather well for 1x and 2x assets in a .atlas folder. Again because everything is converted to points you can have button.png and [email protected] in a texture atlas and the positioning will be the same and look the same for all iPhones.
What about @3x?
This is a better question for Apple. Apparently SpriteKit does not support @3x images in a texture atlas. There are a few question already on SO that have tried to address this.
One example...
Spritekit - not loading @3x images from SKTextureAtlas
It appears it hasn't been fixed in Xcode 6.2 either. If you are reading this and want @3x it might be worth filing a radar with Apple. One thing to note is that I didn't see anywhere in the docs claiming that texture atlases are suppose to support @3x (or even @2x for that matter) When they are supported you won't have to do any changes to your code. Just throw the @3x assets into your .atlas folders.
What can/should I do about the @3x assets?
My advice is to not worry about it and run @2x assets. SpriteKit does a decent job scaling images and there are a lot of apps out there that don't support @3x. As a fellow iPhone 6+ owner it is just something I have learned to live with at the moment. I hope that Apple supports the @3x images in the .atlas folder very soon.
Warnings
You are asking all devices to scale down with the exception of the iPhone 6 (and scaling up iPhone 6+) In most cases you shouldn't notice a big difference in your art (or performance from my testing), but as you know if you shrink images they may look slightly different. Also there is the black bar issue on the 4s which I don't have a solution for you at the moment.
Closing Points
You will get the exact same look and feel in your app across all devices if you set the scene size and set your scene to SKSceneScaleModeAspectFill
however you are asking older devices to scale down. It saves a ton of time and planning with minor draw backs as far as I see it.
Hopefully that helps and the best of luck on your app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With