Why won't my SKSpriteNodes appear in the scene? - swift

I am trying to add a couple of nodes to the scene. When I run the app I just have the default gray background. Neither of the nodes appear in the scene. Here is what I have:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let jumper = SKSpriteNode(imageNamed:"Jumper")
jumper.xScale = 0.25
jumper.yScale = 0.25
jumper.position = CGPointMake(50, 300)
self.addChild(jumper)
let blob = SKSpriteNode(imageNamed:"Blob")
blob.position = CGPointMake(160, 30)
blob.xScale = 0.5
blob.yScale = 0.25
self.addChild(blob)
}
I have checked the image titles and everything is correct there.

The Problem
Your sprites are not visible because your scene is not completely within the simulator's window. By default the scene's size is 1024 x 768 (specified by GameScene.sks), while the simulator is displaying only 375 x 667 points (if you selected the iPhone 6/6s simulator). Unless the scene's size is set correctly, the bottom-left corner of the simulator's window will not be the (0,0) position of your scene.
To correct this issue,
Method 1:
Change the scene's size property in GameScene.sks to match the size of the view. I suggest you set the scene size to 375 x 667 (iPhone 6/6s). If you do this and set the scene's scaleMode property to .AspectFill (the default value), SpriteKit will automatically scale the scene to fit in the view of the iPhone 6+, 6s+, 5, and 5s. This will save you time when porting your game to these devices.
Method 2:
In your view controller, replace this
scene.scaleMode = .AspectFill
with this
scene.scaleMode = .ResizeFill
Warning: Using this method will work but may require additional effort to port your game to other iOS devices with a different screen size.

Related

SpriteKit SKScene not resizing correctly to fit iPhone 12

I've created a new SpriteKit project and want the scene to fill the screen entirely. I have defined the GameScene with iPhone 12 screen dimensions (390pt x 844pt) and specified the following in GameViewController.swift:
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = .aspectFill
view.presentScene(scene)
}
}
However, there is still a large amount of unoccupied space above and below the SKScene. I can't figure out what I've done wrong, and any help would be appreciated.
Fix (credit #aheze)
As mentioned here, this can be fixed by setting the launch screen file in your project settings under App Icons and Launch Images.

Viewport? or Camera? of Field of View? changes on rotating iOS device

I have a 3d world using a SceneKit view in my app.
I need to support all iOS devices and orientations.
I do not understand 3d maths, matrices nor really understand cameras and stuff, yet I've built a 3d world, and I have a camera that works, and orbits with a Pan Gesture an object at the centre of the world.
My problem is that when I rotate the device from portrait to landscape the SceneKit view automatically changes it's perspective (of what I'm not sure - the camera? or the world itself?) and the object that looked like it was close, now goes way back into the distance.
What I want to happen is that regardless of rotation the 'viewport'? or camera? or world perspective? stays the same and the distance the camera is from the object doesn't "look" different i.e. the object visually stays at the same place.
I have not done any matrix manipulations or set up anything complicated.
I understand that the units of SceneKit are metres, so my object is in the correct size, and the camera is the right number of metres from it... it looks 'correct'
What I don't understand is why it all changes in landscape.
Yes, the SceneKit view is using AutoLayout constraints to hug the edges of the screen.
Here is my camera setup:
private func setupCamera() -> SCNNode {
let camera = SCNCamera()
camera.usesOrthographicProjection = false
camera.orthographicScale = 9
camera.zNear = 0.01
camera.zFar = 9500
camera.focalLength = 50
camera.focusDistance = 33
camera.fieldOfView = 100
let cameraNode = SCNNode()
cameraNode.position = SCNVector3(x:0, y:0, z: 500.0)
cameraNode.camera = camera
self.cameraNode = cameraNode
let cameraOrbit = SCNNode()
cameraOrbit.addChildNode(self.cameraNode!)
return cameraOrbit
}
The only way I've found to 'fix' this is to make the SceneKit view always be a square and sized so that it's always the largest of the devices width or height and keep it's centre in the screen's centre.
But this approach isn't working with other parts of the app, so instead I know I need to do this 'properly'.
So would someone please provide the code or tell me what I need to understand so that in the function that gets called when the device rotates i.e. override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) then I can correct this automatic change and keep the view's 'perspective' the same.
Thank you.
After 4 days of playing with constraints, manually moving the frame and all sorts of stuff, I have fixed it.
I constrained the scenekitview to the superview with 0 constants, so it's always the size of the screen.
Then ALL I had to do to solve this is ONE LINE... sigh.
I just had to halve the 'sensorHeight' and then it worked perfectly.
if UIDevice.current.orientation == .landscapeLeft ||
UIDevice.current.orientation == .landscapeRight
{
self.cameraNode?.camera?.sensorHeight = 12
}
else
{
self.cameraNode?.camera?.sensorHeight = 24
}
EDIT:
Because of the constraints to the screen size, the default Field of View meant that you have a fish-eye effect.
Dropping the FoV to almost half cured this and now objects rotate without distortions:
camera.fieldOfView = 50
From ios11 you can also tell scenekit which projection to use.
This solved it for me and is aspect ratio independent.
camera.projectionDirection = isPortrait ? .vertical : .horizontal

How to prevent distorted images?

I have the problem that the images I add are distorted. I have created a pixel accurate background for the iPhone X at (1125 x 2436), so I don't have to use .aspectFill and .aspectFit because I want a screen without black borders.
I use the following code to create the images:
func animateDeck() {
let chip = SKSpriteNode(imageNamed: "Chip")
chip.position = CGPoint(x: 300, y: 400)
chip.zPosition = 2
chip.setScale(1)
gameScene2.addChild(chip)
print("test")
}
Is there a way to display the images in their correct size without using .aspectFit or .aspectFill?
now (left) and how it should be (right)
Thank you in advance!
Check out this project I just made to show you how to create a texture and apply it to a node. All you need should be in GameScene.swift.
Also, in your ViewController, make sure that your GameScene is initialised properly as shown in my project, or how you did it with this:
gameScene2 = GameScene(size: view, bounds: size)

Background of spriteKit exceeds the frame of the phone IOS

I am having deep trouble understanding how the resolution on different devices work. so what I have done is made a background image 1024 x 768 then tested on an iphone 5 device. when i run it, the bottom half of the screen is chopped off so as the top. I did use AspectFill as my scale mode, but even when i test it on iphone 6 or 6+, the background is still chopped off.
the following is my code for gameviewcontroller
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene(size: CGSize(width: 1024, height: 768))
let skView = self.view as! SKView
skView.multipleTouchEnabled = true
if GameSettings.Debugging.ALL_TellMeStatus {
skView.showsFPS = GameSettings.Debugging.ALL_ShowFrameRate
skView.showsNodeCount = GameSettings.Debugging.ALL_ShowNodeCount
skView.showsDrawCount = GameSettings.Debugging.IOS_ShowDrawCount
skView.showsQuadCount = GameSettings.Debugging.IOS_ShowQuadCount
skView.showsPhysics = GameSettings.Debugging.IOS_ShowPhysics
skView.showsFields = GameSettings.Debugging.IOS_ShowFields
}
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
_ = SGResolution(screenSize: view.bounds.size, canvasSize: scene.size)
skView.presentScene(scene)
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .Landscape
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
and my code for adding the background image in.
let background = SKSpriteNode(imageNamed: "Artboard 1")
background.posByCanvas(0.5, y: 0.5)
background.xScale = 1.2
background.yScale = 1.2
background.size = self.frame.size
background.zPosition = -1
addChild(background)
is this the right way to start the screen size or should i start with an iPad screen size then descale it? If anyone can lead me on how to attack this problem that would be great!!
Aspect fill is going to chop off parts of your background.
Your scene has an aspect ratio of 4:3
Your device has an aspect ratio of 16:9
AspectFill will scale your scene in its current aspect ratio(4:3) till the farthest borders are filled, allowing for the entire view to show the scene and have no black borders;
AspectFit will scale till the nearest borders are filled in, which will give you black bars to preserve the aspect ratio.
If you want the 4:3 to not be preserved, then you use .Fill, this of course is going to make your sprites fatter on 16:9 because it will just stretch the scene till it hits all 4 borders
Finally you have .ResizeFill, and what this does is resizes the scene bounds to match your screen size, so if you start with a 1024x768 scene, it will turn it into a 736x414 scene when you view it on iPhone 6+ (This is because we are working in points, not pixels, the pixel count would be x3 (so 2208x1242) which hardware will shrink to 1920x1080).
You need to take a step back and evaluate how you want your game to look on 3 different aspect ratios
16:9,3:2, and 4:3, and determine which of the 4 methods above works best for you.
Now in my opinion, I find that Aspect Fill works best, and I just plan for the 16:9 aspect ratio, making sure I do not put any important information in the areas that may be cropped for a game, but this does not work for everybody, and unfortunately nobody can help you with this part, since it is your game and you are the one that determines its look and feel.

resizing scene with swift and spritekit

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)