For some reason my code will not fill the whole SKScene. Here is the code that I am using on Xcode 12 Beta 5.
GameScene.swift
class GameScene: SKScene {
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: "space")
background.zPosition = 0
background.anchorPoint = CGPoint(x: 0.5, y: 0.5) // default
background.position = CGPoint(x: frame.midX, y: frame.midY)
print("frame.size \(frame.size)")
print("self.size \(self.size)")
print("view \(view.frame.size)")
background.size = CGSize(width: self.size.width, height: self.size.height)
self.addChild(background)
}
}
GameViewController.swift
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GKScene(fileNamed: "GameScene") {
if let sceneNode = scene.rootNode as! GameScene? {
// Present the scene
if let view = self.view as! SKView? {
sceneNode.size = view.bounds.size
sceneNode.anchorPoint = CGPoint.zero
sceneNode.scaleMode = .aspectFit
print("view.bounds.size \(view.bounds.size)")
view.presentScene(sceneNode)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override var prefersStatusBarHidden: Bool {
return true
}
}
Also for some reason, my view size is reporting ->
frame.size (320.0, 480.0) self.size (320.0, 480.0) view (320.0,
480.0)
But my GameScene.sks is set to -> w750, h1336
Why is my code cutting off the tops and the bottoms of the background?
This is going to sound dumb, but do you have a launch Screen? I was having the same problem which would only happen in Xcode 12 and not 11, but the main difference I found was Xcode 11 has a launch screen. Once I added the launch screen storyboard and added it to my plist my SCNView would fill the screen. I am not sure why this would cause the view not to follow the constraints, but after adding it to my other projects it fixes the issue.
Edit:
You do not need to have a launch screen storyboard, you can just add your main storyboard that displays you scene in the plist under "Launch screen interface file base name".
This is definitely caused by not having a launch screen assigned. It's very odd that Xcode 12 has this behavior for SpriteKit by default. I'm sure many many people will be stumped and confused. I noticed that the main visible difference to earlier versions was the lack of a launch screen.
You can either create a launch screen and assign it or define Main.storyboard as the launch screen, as proposed earlier. Probably the easiest thing to just get it working is to go to the project target, then General and choose "Main" where it says "Launch Screen File". This will make it work as expected.
Update: This is still happening in Xcode 12.4 (12D4e). Surprisingly, the launch screen will be missing in a brand-new iOS-only project, whereas it's there in a multi-platform project. It seems like this is an oversight on Apple's part.
How to select Main as your project's Launch Screen File:
Related
My SKScene will show sized correctly in the Simulator, before rotation, but not after?
If the Simulator is preset to Portrait, my SKScene is sized correctly .. and ditto if preset to Landscape.
But, not after rotation-in-place.
Here are some code snippets …
class GameViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// thisScene = a String name, e.g. “CreditsScene” or “AboutScene”
showScene(theScene: thisScene!)
} // viewDidAppear
func showScene(theScene: String) {
view = SKView()
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: theScene) {
scene.scaleMode = .aspectFill
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
} // showScene
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
if fromInterfaceOrientation.isLandscape {
let width = UIScreen.main.bounds.width
let height = UIScreen.main.bounds.height
if let scene = SKScene(fileNamed: thisScene!) {
print("\(scene)")
scene.size = CGSize(width: width, height: height)
print("\(scene)")
}
}
else {
let width = UIScreen.main.bounds.width
let height = UIScreen.main.bounds.height
if let scene = SKScene(fileNamed: thisScene!) {
print("\(scene)")
scene.size = CGSize(width: width, height: height)
print("\(scene)")
}
}
showScene(theScene: thisScene!)
} // didRotate
}
Here’s the Console output after rotation from Portrait to Landscape:
name:'(null)' frame:{{-375, -667}, {750, 1334}} anchor:{0.5, 0.5} // before Landscape
name:'(null)' frame:{{-590, -410}, {1180, 820}} anchor:{0.5, 0.5} // after Landscape
Then, after rotation back to Portrait:
name:'(null)' frame:{{-375, -667}, {750, 1334}} anchor:{0.5, 0.5} // before Portrait
name:'(null)' frame:{{-410, -590}, {820, 1180}} anchor:{0.5, 0.5} // after Portrait
The 2nd lines, “after ..” reverse as they should.
For the life of me, I do not understand the 1st lines, “before”?
and for both lines what is name:'(null)' .. doesn't it have the name fileNamed:thisScene!
It’s almost as if
if let scene = SKScene(fileNamed: theScene) { .. }
doesn’t call view.presentScene( .. )
To complete the diagnostics, I have one GameViewController and 3 GameScenes (.sks files). I am successful in switching scenes .. but not in rotating them to size.
Any help is very, very appreciated!
SOLVED
See the above code for showScene, in particular the 1st line in the func showScene:
view = SKView()
Eliminate it.
Found this jewel here at SO:
The size specified in the .sks file is the size of the scene not the view. Set your scene's scale mode to .resizeFill to force the scene size to always match your view size.
scene.scaleMode = .resizeFill
BOOM!
DONE!
I'm trying to be a competent iOS Programmer ... I have no aspirations to be a Movie Producer, but:
lovesongforever.com/monsterpaddle
I started studying SpriteKit recently with one famous textbook and immediately a problem arose. In all video lessons, SKView covers the entire display area. I have the opposite situation and I don't know how to fix it. Here are the screenshots:
iPhone with notch
classic iPhone
Here is the source code:
GameViewController.swift:
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Set the scale mode to scale to fit the window
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.ignoresSiblingOrder = true
let scene = GameScene(size: CGSize(width: 2000, height: 1500))
scene.scaleMode = .aspectFill
// Present the scene
skView.presentScene(scene)
}
override var shouldAutorotate: Bool {
return true
}
override var prefersStatusBarHidden: Bool {
return true
}
}
GameScene.swift:
import SpriteKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
backgroundColor = .brown
}
}
I don't know if anyone had such problems before the macOS 11 and Xcode 12, but now they are.
How to stretch SKView across all screen?
Set your project's Lauch screen file to "Main".
Could use some help troubleshooting an issue with a SpriteKit scene.
I have a scene that displays some coins in the main section of the app.
When I present a viewcontroller from the bottom I have no issue. Same for tab bar navigation, no issues.
Here is the view as it should always be displayed.
The issue comes only when I present a viewcontroller from the side.
When the new viewcontroller is dismissed, the scene works, but is distorted.
this is how it is displayed after a viewcontroller is displayed modally and later on dismissed.
EDIT: I forgot to mention that if I swipe vertically on the distorted scene, the distortion is fixed and all is good.
Here is some of the code in viewDidAppear of the viewcontroller.
Thanks for the help.
EDIT 2:
I just tested the app on a iPhone 5 using iOS 10 and the issue doesn't happen. Any chance this might be iOS 11 related?
func configureScene(_ completion: () -> Void) {
defer { completion() }
guard wScene == nil else { return }
let skView = SKView(frame: self.view.frame)
skView.isUserInteractionEnabled = false
skView.backgroundColor = .clear
wScene = WScene(size: view.frame.size)
wScene.backgroundColor = .clear
skView.presentScene(wScene)
view.insertSubview(skView, belowSubview: collectionView)
if let buttonsObstacle = doubleButton?.buttonsView {
let obstacleSize = CGSize.init(width: buttonsObstacle.frame.width, height: buttonsObstacle.frame.height)
obstacle = SKSpriteNode.init(color: .clear, size: obstacleSize)
guard let obstacle = obstacle else { return }
obstacle.name = WScene.obstacleNodeName
let convertedOrigin = view.convert(buttonsObstacle.center, from: buttonsObstacle.superview)
let skConvertedOrigin = skView.convert(convertedOrigin, to: wScene)
obstacle.position = skConvertedOrigin
obstacle.physicsBody = SKPhysicsBody(rectangleOf: obstacleSize)
obstacle.physicsBody?.allowsRotation = false
obstacle.physicsBody?.isDynamic = false
source.scrollHandler = { [weak self] (scrollView) in
guard let strongSelf = self else { return }
strongSelf.buttonsMoved(inView: skView, withScroll: scrollView)
}
wScene.addChild(obstacle)
presenter.loadData()
}
}
I solved my issue.
It was related to the new iOS 11 adjustedContentInset property.
My Coin SK scene was being moved by the scroll handler when the view appeared after a modal transition.
My solution is to disable the scrolling for the first 0.1 second after the view appears. In this way iOS 11 doesn't touch the coins anymore while users are able to scroll correctly because they interact with the view most of the time after at least 0.1 seconds.
I am having a problem with my xCode project. I have a whole gamescene.swift file worth of code (600 lines). But the code will not run. When i run my game in simulator the simulator shows the standard gamescene.sks color, alongside with my ads, but it is not showing any of my code. I have already checked that the custom class in gamescene.sks is correct. Everything is working, expect for the gamescene.swift code, it will not run.
import UIKit
import SpriteKit
import GameplayKit
import GoogleMobileAds
class GameViewController: UIViewController {
#IBOutlet weak var GoogleBannerView: GADBannerView!
#IBOutlet weak var MainMenu: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
GoogleBannerView.adUnitID = "ca-app-pub-13***46014918193/236762****"
GoogleBannerView.rootViewController = self
GoogleBannerView.load(GADRequest())
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 = .resizeFill
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = true
}
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override var prefersStatusBarHidden: Bool {
return true
}
}
i managed to fix the problem after countless hours of trying.
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = GameScene(fileNamed: "GameScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .resizeFill
this is the working code. the problem was that instead of specifying what scene i was suppose to lead i had written
if let scene = SKScene(fileNamed: "GameScene")
the simple fix was changing the "SKScene" to my SKScene name.
if let scene = GameScene(Filenamed: "GameScene")
Hope this helps the countless other out there that are having trouble with this problem!
I've had similar problems to this on SOME of my projects but not all. Even on projects that were working and I duplicated the code and scene files for another project they would stop working. I discovered that if there are any spaces or special characters in the your project name the scene files and items in the sks files will not load unless you put in the "Module" name below the Custom Class type.
For me my project was named "Crag & Pig" before any of the sks file would register I had to enter "Crag_Pig" in the "Module" for all of the items in the sks file.
Interestingly, on any projects that didn't have spaces or special characters I didn't have to enter any thing for Module
Thanks. Even the default template in Xcode for SpriteKit Games has this very issue. That since the release of swift 4 + iOS 11.
I always thought it was me somehow, but never took the time to find why. Until now out of curiosity. I changed the line you wrote/fixed and voila.
Just changed the capitals in the parameter fileNamed: of your line
if let scene = GameScene(fileNamed: "GameScene")
So I'm trying to learn Swift and Sprite kit and I started following this Apple tutorial (you might need to login to Apple Developer):
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/GettingStarted/GettingStarted.html#//apple_ref/doc/uid/TP40013043-CH2-SW1
I translated the code given from Obj-C to Swift and it works quite well BUT my SKLabelNode named helloNode is not showing up despite the fact that Sprite kit is telling me that there is indeed 1 node on scene.
Here's the code:
class HelloScene: SKScene {
var contentCreated = false
override func didMoveToView(view: SKView) {
if(!self.contentCreated) {
createSceneContents()
contentCreated = true
}
}
func createSceneContents() {
self.backgroundColor = SKColor.blueColor()
self.scaleMode = SKSceneScaleMode.AspectFit
self.addChild(newHelloNode())
}
func newHelloNode() -> SKLabelNode {
let helloNode = SKLabelNode(fontNamed: "Chalkduster")
helloNode.text = "Hello, World!"
helloNode.fontSize = 42
helloNode.fontColor = SKColor.whiteColor()
helloNode.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))
return helloNode
}
}
HelloScene is instantiated and successfully added to the main View Controller.
Thanks!
I had the same issue. The issue is with auto layout in xcode 6. The scene is being loaded before the auto layout settings are set. In the ViewController place the initialization of the scene and presentScene in viewDidLayoutSubviews like so:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews();
let hello = HelloScene.new();
hello.size = skView.bounds.size;
hello.scaleMode = SKSceneScaleMode.AspectFill;
skView.presentScene(hello);
}