How do you change the presented view of an SKScene?
You're not supposed to alter the scene's size
in this manner. Creating a scene of 7000*7000 points would have a Retina iPad render 98 megapixels 60 times per second. Ouch.
Scale a child node
Simply create a new SKnode sceneContents
and add your SKShapeNode as a child to this node. When you wish to "zoom", scale down the sceneContents
node (through the xScale
and yScale
properties of SKNode). You can use SKAction for this, so it's nice and smooth.
SKCameraNode
If you can move to iOS 9, I would recommend looking into SKCameraNode. This is still in beta at the moment but it works nicely.
Simply create an SKCameraNode, add it to the scene and set it to be the camera for the scene.
SKCameraNode *camera = [SKCameraNode new];
[self.scene addChild:camera];
self.scene.camera = camera;
camera.xScale = 10.f;
camera.yScale = 10.f;
Hm, I should learn Swift at some point. Nevertheless, the concept should be clear. You can use SKAction to manipulate the camera node with an animation.
Make SKScene fill whole screen using Swift
I had to manually add an image set named LauchImage
in the Images.xcassets
.
How to edit a property of GameViewController from GameScene
This was happened because you re-create the GameViewController
inside your scene with the line:
var viewController = GameViewController()
instead of get the already existent GameViewController
.
There are many ways to solve your issue.
So, for example using the "hello world" Sprite-kit template if you have your GameViewController
as the initial viewController of your game you can do:
GameViewController:
import UIKit
import SpriteKit
class GameViewController: UIViewController {
var uiLabelContainer:UILabel!
override func viewDidLoad() {
super.viewDidLoad()
uiLabelContainer = UILabel(frame: CGRect(x:0,y: 0,width: 250,height: 50))
uiLabelContainer.textAlignment = NSTextAlignment.left
uiLabelContainer.textColor = .white
uiLabelContainer.text = "This is a Label"
self.view.addSubview(uiLabelContainer)
uiLabelContainer.isHidden = true
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = .aspectFill
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
func printStuff() {
print("printStuff")
}
}
GameScene:
import SpriteKit
class GameScene: SKScene {
private var label : SKLabelNode?
var viewController : GameViewController!
override func didMove(to view: SKView) {
self.label = self.childNode(withName: "//helloLabel") as? SKLabelNode
if let label = self.label {
label.alpha = 0.0
label.run(SKAction.fadeIn(withDuration: 2.0))
}
self.run(SKAction.wait(forDuration: 2),completion:{[unowned self] in
let appDelegate = UIApplication.shared.delegate as! AppDelegate
if let vc = appDelegate.window?.rootViewController {
self.viewController = vc as! GameViewController
self.viewController.uiLabelContainer.isHidden = false
}
})
self.run(SKAction.wait(forDuration: 5),completion:{[unowned self] in
let scene2 = GameScene2()
scene2.scaleMode = .aspectFill
self.view?.presentScene(scene2)
})
}
deinit {
print("\n THE SCENE \((type(of: self))) WAS REMOVED FROM MEMORY (DEINIT) \n")
}
}
GameScene2:
(created only for test, to see the correct GameScene
deallocation)
import SpriteKit
class GameScene2: SKScene {
private var label : SKLabelNode?
override func didMove(to view: SKView) {
print("gameScene2")
}
}
Output:
How to add an .sks files to existing Swift/Sprite-Kit project?
The reason why you are getting the required is because you have variables that are not optional or not initialized before init takes place.
If you have variables that need to be assigned inside of an init function, then you would do:
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
But then you will ask me: Mr Knight0fDragon, it is telling me to replace fileNamed
with coder
, and it is not compiling when I switch it.
Well this is because init(fileNamed:)
is a convenience init, not a designated init. In order to be able to subclass a class and get all of it's convenience inits, you need to override all of it's designated inits.
Now with SKScene, you have 3, and you already know about 1.
Let's override the other 2:
override init() {
super.init()
}
override init(size: CGSize) {
super.init(size: size)
}
Alright, now this puppy should be ready to compile, we just need to get the variables assigned.
Well what I like to do is create a setup method for any variable that has to be assigned in any version of initialization after the super is called.
Unfortunately we can't do this for constants before super is called, so those we would need to set up in each method. The reason being is that self
does not fully exist yet.
This would end up looking like this:
let constant : String
required init?(coder aDecoder: NSCoder)
{
constant = "hi"
super.init(coder: aDecoder)
setup()
}
override init() {
constant = "hi"
super.init()
setup()
}
override init(size: CGSize) {
constant = "hi"
super.init(size: size)
setup()
}
Gamescene.sks and GameScene.swift don't seem to be linked in my project
We have a normal GameScene.swift
that should be print "hello" with his GameScene.sks
called by a GameViewController
. You did not specify what is GameController
but this is not a problem because I think you could simply lost the flow of your game so I try to help you about it (dont' worry,
it happens when you are focused on the rest of the game a long time and can not remember the starting flow).
In your Main.storyboard
you probably don't have a situation like this:
where your GameViewController
is the initial view controller.
What I mean is you should check who call GameViewController
on your storyboard or if your AppDelegate.swift
(in didFinishLaunchingWithOptions
) stop the flow or call other views before calling GameViewController
.
So , check who is the IVC (initial view controller) and be sure your GameViewController
is called from start or by other viewControllers using breakpoint or simply launch this print in your viewDidLoad
:
print("∙ \(type(of: self))")
Another situation could be happen when you add or remove files with the same name in library. In this case try to remove GameScene.swift
and GameScene.sks
, clean and build your project and re-add these files (be sure as your screen GameScene.sks have the right custom class..)
Check your Compile Sources list to control your GameScene.swift
Hope it helps.
SKScene Viewable Size smaller than View bounds
I think this might be because Apple has mistakenly removed the launch screen from the iOS-only SpriteKit game template (it's still there in the multi-platform template). You need to either add and assign a launch screen or choose Main as your launch screen.
The launch screen defines the working area for the app, so without it the view bounds and scene scale mode will not fix this issue.
More info in Background is not filling the whole view SpriteKit.
Trouble using SKReferenceNode programmatically
As I mentioned in another post, I found a workaround.
In my case, I substituted the SKReferenceNode with an SKScene.
I first made sure that, in my .sks scene, all SKSpriteNodes were children of one main node. It doesn't have to be a direct link, you can still respect the hierarchies of your scene, but it's important that at the end of the "hierarchy tree" they are linked to one node, which in my case is the background, but it can also be an empty node.
In my GameScene file I then wrote the following code:
class GameScene: SKScene {
var mainNode: SKNode? = nil
override func didMove(to view: SKView) {
var mySksScene = SKScene(fileNamed: "Caribbeans")
mainNode = upperBackground?.childNode(withName: "backgroundCaribbean")
mainNode?.removeFromParent()
mySksScene = nil
addChild(mainNode)
}
}
I first declared an optional SKNode variable. Then, inside didMove(:to:), I loaded my .sks file in an optional SKScene() variable. I then set SKNode as the main node, the node which is the parent of all the other nodes (in my case: backgroundCaribbean). I then removed my mainNode from its parent scene, THEN set to nil the variable that used to contain the .sks scene, and only THEN I added my mainNode as a Child of my GameScene.
Related Topics
Extract Reality Composer Scene for Arquicklook
Dynamictype of Optional Chaining Not The Same as Assignment
What Do Detached and Assigncurrentcontext Meaning
Crashlytics Doesn't Work with Xcode 10 Beta
Upload Multiple Images to Ftp Server in iOS
Swiftui Map Overlays Without UIviewrepresentable
Swift - Connect Delegate to Custom Xib Cell
Apple Mach-O Linker Error (Static, Not Ld)
Why Is Swift Giving Me Inaccurate Floating Point Arithmetic Results
Force Refresh on Another Viewcontroller Component with Swift
Swift Set UIbutton Setbordercolor in Storyboard
Siblings Relationship Between Same Models in Vapor
How to Grab The Parent Object from a Subview
Parse Migration Error to Mlabs and Heroku
Swift 3 Custom Extension of Ns Measurement? Ex. Sheeps to Goats