How to Scale/Position Nodes Swift Spritekit? Custom View

How to scale/position nodes Swift SpriteKit? Custom View?

To keep my games universal I make all my nodes sizes and positions dependant on SKScene size

Instead of using hardcoded numbers try using proportions from your SKScene size. For example:
Instead of writing this:

node.position = CGPointMake(100, 100)

Write somthing like this:

node.position = CGPointMake(world.frame.size.width / 32 * 16, world.frame.size.height / 18 * 9)

world - SKNode of exactly same size as your SKScene

Same for sizes

let blackSquare = SKSpriteNode(texture: nil, color: UIColor.blackColor(), size: CGSizeMake(world.frame.size.width / 32, world.frame.size.width / 32))

Also GameViewController should look something like this:

override func viewDidLoad() {
super.viewDidLoad()

// Configure the view

let skView = view as! SKView
skView.multipleTouchEnabled = false

// Create and configure the scene

let scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
scene.size = skView.bounds.size

skView.presentScene(scene);
}

Was this helpfull?

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

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/

Spritekit Camera Node scale but pin the bottom of the scene

You cannot use a constraint because your scale size is dynamic.

Instead you need to move your camera position to give the illusion it is only scaling in 3 directions.

To do this, I would recommend creating a custom action.

let scaleTo = 2.0
let duration = 1.0
let currentNodeScale = 0.0
let scaleTop = SKCustomAction(withDuration:duration){
(node, elapsedTime) in
if elapsedTime == 0 {currentNodeScale = node.scale}
let newScale = currentNodeScale - ((elapsedTime/duration) * (currentNodeScale-scaleTo))
let currentYScale = node.yScale
let currentHeight = node.scene.size.height * currentYScale
let newHeight = node.scene.size.height * newScale
let heightDiff = newHeight - currentHeight
let yOffset = heightDiff / 2
node.scale(to:newScale)
node.position.y += yOffset

}

What this is doing is comparing the new height of your camera with the old height, and moving it 1/2 the distance.

So if your current height is 1, this means your camera sees [-1/2 to 1/2] on the y axis. If you new scale height is 2, then your camera sees [-1 to 1] on the y axis. We need to move the camera up so that the camera sees [-1/2 to 3/2], meaning we need to add 1/2. So we do 2 - 1, which is 1, then go 1/2 that distance. This makes our yOffset 1/2, which you add to the camera.

SpriteKit - Scale node to X from right to left

I believe a simpler solution is to change the anchor of your node.

loadBarNode.anchorPoint = CGPointMake(0.0, 0.5)

Scaling is based on the anchorPoint of your node and this would cause it to expand to the right.

How can I make SKSpriteNode positions the same for any simulator/device?

If you are making a Universal application you need to declare the size of the scene using integer values. Here is an example:

scene = GameScene(size:CGSize(width: 2048, height: 1536))

Then when you initialize the positions and sizes of your nodes using CGPoint and CGSize, make them dependant on SKScene size. Here is an example:

node.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2)

If you declare the size of the scene for a Universal App like this:

scene.size = skView.bounds.size

then your SKSpriteNode positions will be all messed up. You may also need to change the scaleMode to .ResizeFill. This worked for me.



Related Topics



Leave a reply



Submit