Scale sprite kit game for all devices - ios

When creating my game in spriteKit I used the game size 1080x1920. Now however If I am to run it on Ipad it looks bizarre. Is there an easy fix? I am simply worried that my app will get rejected. Thank you in advance?

Its quite a commonly asked question.
What we usually do in SpriteKt is to give the SKScene a fixed size and let SpriteKit do the scaling for you on different devices.
So basically we have 2 ways to do it correctly
1) Set scene size to iPad (e.g 1024x768 -landscape, 768x1024 - portrait). This was the default setting in Xcode 7.
You than usually just have/show some extra background at the top/bottom (landscape) or left/right (portrait) on iPads which gets cropped on iPhones.
Examples of games that show more on iPads / crop on iPhones:
Altos Adventure, Leos Fortune, Limbo, The Line Zen, Modern Combat 5.
2) Apple changed the default scene size in xCode 8 to iPhone 6/7 (750*1334-Portait, 1334*750-Landscape). This setting will crop your game on iPads.
Examples of games that show less on iPads:
Lumino City, Robot Unicorn Attack
Choosing between those 2 options is up to you and depends what game you are making.
Regardless of scene size scale mode is usually best left at .aspectFill or .aspectFit, again depending on what you prefer and need (e.g cropping with aspectFill or black bars with aspectFit)
You would use the Universal asset slot and/or device specific images. This way you will have a consistent experience on all devices
Spritekit scale full game to iPad
How to make SKScene have fixed width?
Hope this helps

When you present the scene's you also set the aspect ratio.
example :
if let scene = SKScene(fileNamed: "GameScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
}
There are 4 different aspect radios you can set
aspectFit
aspectFill
fill
resizeFill
You can find out about the 4 different types here in the apple documents.
It looks to me that you currently have it set to aspectFill but you would be better off using aspectFit. This will create a black bar on the top and bottom on some devices but it will keep the aspect ratio the same.
If you want it to look good on all devices(no black bar) you would need to check which device it is running on then update the size and position of your sprites accordingly.

Whenever scenes are hard coded, (not made within the editor) using .resizeFill will ensure that the width AND height of the scene ALWAYS conform to the view. So your game will scale correctly on any device. For scenes that are made within the editor, this is not the case.
Personally, I hardcoded all the levels in my game "Astro Path" (it's on the app store for reference) and used .resizeFill so it would scale correctly on any device without any cropping or black bars. (who wants that stuff yuck) For my title screens, I used:
.aspectFill on iPhone
.fill on iPad
because they were designed within the editor. I checked for the current device using: if UIDevice.current.userInterfaceIdiom == .pad { do w/e }

Related

How do I size sprites in a universal sprite kit game

I'm relatively new to swift programming. I have made an app where I didn't use SpriteKit and I would size most views by scaling down the images to a multiple of the screens width and height. Not sure if this is the best tactic, but it worked and I was able to build an app that looked good on all devices.
With spritekit and the scene.sks files, I don't have the option of auto-layouts to size my sprites like I did before. There isn't a lot of content about universal apps online, so I'm struggling to find a solution.
My question is how do I go about sizing objects and making sure my scenes look the same across different devices?
If you have a good example that could explain this that would be very helpful. Thank you!
What we usually do in SpriteKt is to give the SKScene a fixed size and let SpriteKit do the scaling for you on different devices.
So basically we have 2 ways to do it correctly
1) Set scene size to iPad (e.g 1024x768 -landscape, 768x1024 - portrait). This was the default setting in Xcode 7.
You than usually just have/show some extra background at the top/bottom (landscape) or left/right (portrait) on iPads which gets cropped on iPhones.
Examples of games that show more on iPads / crop on iPhones:
Altos Adventure, Leos Fortune, Limbo, The Line Zen, Modern Combat 5.
2) Apple changed the default scene size in xCode 8 to iPhone 6/7 (750*1334-Portait, 1337*750-Landscape). This setting will crop your game on iPads.
Examples of games that show less on iPads:
Lumino City, Robot Unicorn Attack
Choosing between those 2 options is up to you and depends what game you are making. I usually prefer to use option 1 and show more background on iPads.
Regardless of scene size scale mode is usually best left at the default setting of .aspectFill.
You would use the Universal asset slot and/or device specific images. This way you will have a consistent experience on all devices
Spritekit scale full game to iPad
How to make SKScene have fixed width?
Hope this helps

How to make SKScene have fixed width?

I am making a spriteKit based game and wonder if I can make the SKScene fixed width (to make it easier to layout the sprites), and let it resize to the actual screen width while keeping the aspect ratio. Is it possible to achieve this goal and is it recommended (will sprites not be rendered clearly due to resizing)?
Giving the scene a fixed size is actually what we want to do in SpriteKit games. SpriteKit will than scale the game for each device using the scaleMode settings (defaults to .aspectFill). Its not a good idea to make the scene the size of the device or use .resizeFill for scale mode as that will lead to massive inconsistencies on different devices. I have been there before with 1 game and it was an absolute nightmare.
So we basically have 2 ways to do it correctly
1) Set scene size to iPad (e.g 1024x768 -landscape, 768x1024 - portrait. This was the default setting in Xcode 7.
You than usually just show some extra background at the top/bottom (landscape) or left/right (portrait) on iPads.
Examples of games that show more on iPads:
Altos Adventure, Leos Fortune, Limbo, The Line Zen, Modern Combat 5.
2) Apple changed the default scene size in xCode 8 to iPhone 6/7 (750*1334-Portait, 1337*750-Landscape). This setting will crop your game on iPads.
Examples of games that show less on iPads:
Lumino City, Robot Unicorn Attack
Choosing between those 2 options is up to you and depends what game you are making. I usually prefer to use option 1 and show more background on iPads.
Regardless of scene size scale mode is usually best left at the default setting of .aspectFill. This way you will have a consistent experience on all devices.
I would not try to do some random hacks where you manually change scene or node sizes/scales on difference devices, you should let xCode/SpriteKit do it for you.
In code you would initialise a SKScene with your preferred size like so
let gameScene = GameScene(size: CGSize(width: 1024, height: 768))
If you use the visual scene editor you set the scene size directly in the inspector panel on the right.
Hope this helps
Any resizing comes with a performance penalty and resizing artifacts such as blurred edges or others.
Scene size is defined by the ViewController when it instantiates the scene before presenting it. Isn't it better to create the scene with the same size as the actual screen size and don't resize it any further?

SpriteKit - How do I handle multiple screen sizes?

My new game is finished and now I'm just testing on multiple real devices. I came across multiple issues after testing. The big issue is how to handle screen sizes. The game is how I want it to look on 6 Plus/6s Plus, but not on 6s, 6, 5s, 5, 4s, 4, or iPad.
I found these two answers but I don't know how to implement them: How to support multiple screen sizes in SpriteKit?
and SpriteKit how to get correct screen size
I really would like any type of help, because this is irritating me.
Its quite a commonly asked question.
What we usually do in SpriteKt is to give the SKScene a fixed size and let SpriteKit do the scaling for you on different devices.
So basically we have 2 ways to do it correctly
1) Set scene size to iPad (e.g 1024x768 -landscape, 768x1024 - portrait). This was the default setting in Xcode 7.
You than usually just have/show some extra background at the top/bottom (landscape) or left/right (portrait) on iPads which gets cropped on iPhones.
Examples of games that show more on iPads / crop on iPhones:
Altos Adventure, Leos Fortune, Limbo, The Line Zen, Modern Combat 5.
2) Apple changed the default scene size in xCode 8 to iPhone 6/7 (750*1334-Portait, 1337*750-Landscape). This setting will crop your game on iPads.
Examples of games that show less on iPads:
Lumino City, Robot Unicorn Attack
Choosing between those 2 options is up to you and depends what game you are making. I usually prefer to use option 1 and show more background on iPads.
For scale mode it is usually best to either use .aspectFill or .aspectFit.
You would use the Universal asset slot and/or device specific images. This way you will have a consistent experience on all devices
Spritekit scale full game to iPad
How to make SKScene have fixed width?
Hope this helps
In my case I have a portrait game, and I want to keep the height fixed while showing more or less content left/right depending on the device's screen.
For that in Xcode's Scene Editor I added and set an SKCameraNode for my scene, and set the scene size to the "widest" aspect ratio device (iPhone X ), that is 2436x1125 pixels.
Then set a custom class for the scene and override sceneDidLoad:
override func sceneDidLoad()
{
super.sceneDidLoad()
self.size.width = self.size.height * (UIScreen.main.bounds.size.width / UIScreen.main.bounds.size.height)
self.scaleMode = .aspectFit
}
If I want to preview how my game will look in the "narrowest" device (any iPad has a 1.5:1 ratio) I just temporarily change my scene's width to around 1500 pixels.
Note: SKView's contentMode changes nothing.
I was reminded of checking the screen size and changing the node sizes, I found this as an answer: how to check screen size of iphone 4 and iphone 5 programmatically in swift
All I had to add was this in my GameScene and it was called in every .swift:
extension UIScreen {
enum SizeType: CGFloat {
case Unknown = 0.0
case iPhone4 = 960.0
case iPhone5 = 1136.0
case iPhone6 = 1334.0
case iPhone6Plus = 1920.0
}
var sizeType: SizeType {
let height = nativeBounds.height
guard let sizeType = SizeType(rawValue: height) else { return .Unknown }
return sizeType
}
}
And this
if UIScreen.mainScreen().sizeType == .iPhone4 {
// Make specific layout for small devices.
}

iOS Universal Device App with SpriteKit, how to scale nodes for all views?

I want to make a landscape app to be universal, so that the sprite nodes scale proportionally to whatever view size is running the app. I'd like an entirely programmatic solution because I don't like the IB.
My game is pretty simple, and I don't need scrolling or zooming of any kind, so the whole game will always be present and take up the entire view.
Is it possible that what I'm looking for is to change the size of the scene to always fit the view? If so, can you explain this thoroughly because I've tried changing this section of my view controller
if let scene = GameScene(fileNamed:"GameScene")
to be the constructor method that takes size as a parameter but Xcode doesn't like that.
Things I've tried
Using fractions of self.view.bounds.width/height. This usually makes all iPhones look good, but on iPads stretches and skews nodes and the boundary box around thew view.
Changing the scaleMode among all four types. I'd like to keep good practice and feel like .AspectFill (default) is the one I should make my app work with, but open to suggestions. Note; I don't want black edges on any device, just the entire view displayed/scaled proportionally.
Applying programmatic constraints. Now I'm fairly new to this and don't understand constraints completely, but no tutorials I've seen even from RayWenderlich talk about constraints on nodes so I didn't delve to deep in this.
Using a method like this to convert points among views. This actually worked pretty well for point positioning of nodes, and if possible I would like this method to work out, but then I still have the problem of sizes of nodes. Also when I build for iPad with this method the view seems to start off as portrait and the nodes look fine but then I have to manually switch it to landscape and the sprites and view boundaries once again get messed up. Here's the method:
func convert(point: CGPoint)->CGPoint {
return self.view!.convertPoint(CGPoint(x: point.x, y:self.view!.frame.height-point.y), toScene:self)
}
Countless vid tutorials on RW and everywhere else on internet.
Thanks in advance! I appreciate the help. I know this topic is weird because a lot of people ask questions about it but everyone's situation seems to be different enough that one solution doesn't fit all.
I initially tried to do the scaling myself with 2 games and it was just madness (scene size = view size or scene scale mode = .ResizeFill). You have to adjust all values e.g font size, sprite sizes, impulses etc for all devices and it will never be consistent.
So you have 2 options basically
1) Set scene size to 1024X768 (landscape) or 768x1024 (portrait). This was the default setting in Xcode 7.
You than usually just have/show some extra background at the top/bottom (landscape) or left/right (portrait) on iPads which gets cropped on iPhones.
Examples of games that show more on iPads / crop on iPhones:
Altos Adventure, Leos Fortune, Limbo, The Line Zen, Modern Combat 5.
2) Apple changed the default scene size in xCode 8 to iPhone 6/7 (7501334-Portait, 1337750-Landscape). This setting will crop your game on iPads.
Examples of games that show less on iPads:
Lumino City, Robot Unicorn Attack
Chosing between the 2 options is up to you and depends what game you are making. I usually prefer to use option 1 and show more background on iPads.
Regardless of scene size scale mode is usually best left at the default setting of .aspectFill.
To adjust specific things such as labels etc you can do it this way
if UIDevice.current.userInterfaceIdiom == .pad {
...
}
You can try the scene scaling yourself, create a new SpriteKit sample game project. Run on all iPhones and you will notice the HelloWorld label looks perfect on all devices.
Now change the default settings to scene size = frame or use .ResizeFill, the HelloWorld label is not scaled properly anymore on all devices.
As a side note, the line
if let scene = GameScene(fileNamed: "GameScene")
references the GameScene.sks file. You said you do everything programatically, therefore you can probably delete the GameScene.sks file and change the line to
let skView = view as! SKView!
let scene = GameScene(size: CGSize(width: 1024, height: 768)) // 768 x 1024 if portrait
Update:
I am now using a slightly different variant as I had problems adapting my game to iPhoneX. I set scene size to 1334x750 and use aspect fit as scale mode. I than run some code to remove the black bars if needed e.g. on iPads or iPhone X. It’s based on this great article (link no longer works).
http://endlesswavesoftware.com/blog/spritekit-skscene-scalemode/

How to scale app so iPhone 6 is identical(zoomed) to iPhone 5 SpriteKit

Ive been making an app using sprite kit in Xcode 7. I made all my sprite nodes positioned around by referencing other sprite nodes and self.frame
for example
self.block.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)
When I came to test my app on an iPhone 6 Plus (I previously tested on iPhone 4s but it worked nicely on an iPhone 5) My app didn't scale the nodes, Just the space Between them. The game relies on everything being the same otherwise people playing on an iPhone 6 would find it easier then people playing on a smaller device. Is there anyway that I could make the iPhone 6 view just a stretched version of the iPhone 5 view? Thanks Guys!
It's best not to position your sprites using self.frame as a reference. Much better to treat the scene as the "true" coordinates and let SpriteKit scale your scene for you.
ie. Specify the scale mode of your scene when you create it (probably in the view controller viewDidLoad). I prefer AspectFill for the scale mode, which makes sure the screen is filled, but you will lose the edges on some devices. Just make sure the core gameplay is in the middle of the scene.
scene.scaleMode = .AspectFill
Then, position your sprites using the size of your scene for reference. On a landscape scene, I tend to use a scene size of 1024x768 (iPad size).
Hope that helps.
Another way: If you remove the iPhone 6 and iPhone 6+ launch images from the project then those devices will switch to "zoom mode", which is exactly the same view as on iPhone 5, just bigger (well, zoomed).
Just look in your project for "Images.xcassets", there is a image-set called "LaunchImage". In this image-set are multiple other images, just remove the one for iPhone 6 and 6+.

Resources