ljs ljs - 1 year ago 128
iOS Question

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

  1. 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.

  2. 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.

  3. 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.

  4. 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)

  5. 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.

Answer Source

The best way is to leave it at the default settings. So scene size is 1024X768 (landscape) and you use AspectFill for scale mode. You than position your stuff towards the centre and usually just have some extra background at the top/bottom on iPads. This way you can use the universal images in your assetCatalogue and everything in your game will look the same on all devices (except the aforementioned extra space on iPads at the top/bottom).

To understand more about scaleModes you can read this


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: skView.bounds.size)