resizing scene with swift and spritekit - iphone

Im making a game with swift and spriteKit with xcode 6.1.
My problem is that, when I run the game on the iPhone 6 or iPhone 6+ the scene/images dont resize properly
I have this on my GameViewController
// Configure the view.
let skView = view as SKView
skView.multipleTouchEnabled = false
// Create and configure the scene.
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
// Present the scene.
skView.presentScene(scene)
And this on my GameScene
override init(size: CGSize) {
super.init(size: size)
anchorPoint = CGPoint(x: 0.5, y: 0.5)
let background = SKSpriteNode(imageNamed: "Background")
addChild(background)
}
I have tried all the scale modes but they dont seem to work. I hope someone can tell me what is going on

The size of the scene is being set to the size of the view in
scene = GameScene(size: skView.bounds.size)
so it is only the images in the scene that are too small to fill the view.
Make these changes to your GameViewController:
if you set the size of the scene to the size of the background image:
scene = GameScene(size: CGSize(width: backgroundImageWidth, height: backgroundImageHeight))
(replace backgroundImageWidth and backgroundImageHeight with actual values)
then set the scene's scale mode to fill the view:
scene.scaleMode = .Fill
(this may make the scene look stretched, you could use other scale modes)

Related

How to create a playable rectangle in SpriteKit on iPhone X

I'm a newbie in Swift and SpriteKit. I'm trying to develop a simple 2D game for iPhone X, so I want to draw a playable area where I can put game's sprites. The problem is that when I draw the rectangle it fits the screen width, but not the screen height.
The GameScene size is 2048x1536, with anchor point in (0.5, 0.5).
The default screen orientation is landscape.
This is what I did at the moment:
GameViewController.swift
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
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)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
GameScene.swift
class GameScene: SKScene {
override func didMove(to view: SKView) {
let rectangle = SKShapeNode(rect: self.frame)
rectangle.strokeColor = .green
rectangle.lineWidth = 20
rectangle.zPosition = 1
addChild(rectangle)
}
}
When I run this code, the rectangle green borders fit the width of the screen (in landscape), so I can see them, but the top and bottom borders are off-screen.
My purpose is to have a playable rect as high as the phone screen, and his width should be screen width - left safe area insets (to exclude the notch from the playable area).
Thank you.

How to change SKScene position before presenting?

I am trying to adjust SKScene position based on the device the game is running. For example due to 'top notch' area of iPhone XS Max, I need to subtract that height from SKScene height and position the scene accordingly.
So here is how I calculate the height aka safeAreaHeight in the AppDelegate and subtract from scene height aka sceneHeight:
safeAreaHeight = UIApplication.shared.statusBarFrame.size.height
sceneHeight -= safeAreaHeight
In GameViewController I try to re-position the SKScene like below:
if let view = self.view as! SKView? {
// Load the SKScene from 'MainMenuScene.sks'
if let scene = SKScene(fileNamed: "MainMenuScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFit
scene.size.height = sceneHeight
scene.size.width = sceneWidth
scene.position.y -= safeAreaHeight
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
However, I am getting below error:
SKScene: Setting the position of a SKScene has no effect.
Additionally, I tried to use SKAction to move position of the SKScene as well, then I received below error:
SKScene: Animating the position of a SKScene has no effect.
Thank you for the help.
Well I figured how to achieve this, I am sharing in case it would help someone else.
Inside AppDelegate you get the correct safe area values and store it in a singleton (in my case: safeAreaHeight) for access throughout the app. Subtract the amount from scene height (sceneHeight).
let kWindow = UIApplication.shared.windows[0]
safeAreaHeight = kWindow.safeAreaInsets.top + kWindow.safeAreaInsets.bottom
screenHeight = screenRect.size.height - safeAreaHeight
Don't forget the adjust the sceneHeight in GameViewController before presenting it:
if let view = self.view as! SKView? {
// Load the SKScene from 'MainMenuScene.sks'
if let scene = SKScene(fileNamed: "MainMenuScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFit
scene.size.height = sceneHeight
scene.size.width = sceneWidth
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
Inside loaded scene, in this case it is MainMenuScene, you simply find subview of SKScene and adjust its Y position by subtracting the safeAreaHeight at its center
guard let subView = self.view else { return }
subView.center.y -= safeAreaHeight
PS.: Do not adjust all the views in different scenes (ie.: GameScene, GameOverScene etc.) Once you adjust, it remains throughout the app.

Setting background to cover whole screen when using aspect Fit in Swift

When using aspect fit in swift, the sides of the screen are removed. Is there a way I can cover this up by using a background colour to fill the whole screen or use a background image?
Here is the code for creating the scene as aspect fit in the GameViewController
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "mainMenu") {
// setting scene here to aspect fit
scene.scaleMode = .aspectFit
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
scene with aspect fit and background set to clear
scene with aspect fill
scene with aspect fit and background set to green
Make sure you set the screen size for the scene.
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
scene?.size = CGSize(width: screenWidth, height: screenHeight)
After, set scene.scaleMode = .aspectFill
If this doesn’t work, you can try and set the background color by doing this, but I’m unaware if this option will give you what you’re looking for as I didn’t test it.
scene?.backgroundColor = UIColor.white //color you want
Otherwise try setting scene?.size = image.size

Border around screen and not frame?

I'm currently making a game in Swift/SpriteKit and I'm having a problem. Whenever I make the border for my game, the border is always around the iPhone/iPad FRAME and not the screen. So when my ball bounces it goes off of the screen and bounces off the "iPhone FRAME" and not the "scene/frame."
Can someone help me make it so my border is around the SCENE and not the FRAME?
Here is my code:
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
I was meant to say (in comments) that you should set the scene's size to match the view's size, like this: In the GameViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
scene.size = skView.bounds.size
skView.presentScene(scene)
}
}
Note the scene.size = skView.bounds.size which sets the scene's size to a size of the view.

Scene size in Xcode 6 / SpriteKit / Swift

I've been getting stuck doing what should be really simple stuff in Xcode, I am trying to add a sprite to the scene and for it to sit in the bottom left corner:
var groundTexture : SKTexture = SKTexture(imageNamed: "dirt-block")
var ground : SKSpriteNode = SKSpriteNode(texture: groundTexture)
ground.position = CGPointMake(ground.size.width/2, ground.size.height/2)
self.addChild(ground)
This doesn't show anything, so I took a look at what the scene dimensions are and self.frame.size.width and self.frame.size.height are returning a width of 1024 and a height of 768, regardless of orientation.
I want this fixed in landscape mode if that makes any difference to the answer?
I'm obviously missing a very fundamental idea to do with setting up the scene, if anybody could shed any light it would be much appreciated.
Thanks.
You have to edit the GameViewController:
Cut everything from viewDidLoad() except super.viewDidLoad()
Overwrite viewWillLayoutSubviews
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
var skView = self.view as SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.size = skView.bounds.size
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
Also you should set the scene size as you can see
scene.size = skView.bounds.size
Hope this helps
There is also a great Tutorial where this is explained better:
http://www.raywenderlich.com/49721/how-to-create-a-breakout-game-using-spritekit
(Chapter 1 or 2)