I'm having trouble trying to get the frame.width of GameScene into a custom class because I need the scene width for positioning nodes in my custom class init.
HudController.swift snippet
import SpriteKit
class HudController:SKNode {
var width:CGFloat
override init(){
width = GameScene().frame.width //I was hoping to add the scene width here
}
}
The following code crashes on me and I've tried heaps of other solutions with no success.
Can someone please help me with this issue?
Thanks!
UPDATED CODE ===
GameScene.swift
import SpriteKit
class GameScene: SKScene {
var hud = HudController(gameScene: self)
// set as global because I'm using it to also call hud functions in my game
}
HudController.swift
import SpriteKit
class HudController:SKNode {
var width:CGFloat
init(gameScene:SKScene){
width = gameScene.size.width
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Every node in SpriteKit can retrieve the scene where it lives using the scene property.
let node = SKNode()
node.scene
The scene property returns a SKScene?, the value is an optional because if the current node does not belong to a scene, of course there is not scene to retrieve.
Now, you could be tempted to use the self.scene property inside the initializer of your HudController.
class HudController: SKNode {
var width:CGFloat
override init() {
super.init() // error: property 'self.width' not initialized at super.init call
width = self.scene!.frame.width
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
But it will now work because you cannot invoke super.init before having initialized the width property.
Fine, then you could try this.
class HudController: SKNode {
var width:CGFloat
override init() {
width = self.scene!.frame.width // error: use of 'self' in property access 'scene' before super.init initializes self
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Again compiler error because you are using self before having called super.init().
And finally there is another problem, when the initializer is executed, the node it is being created has not a parent yet, so the self.scene property does return nil.
How to solve this?
First of all declare you initializer to receive a GameScene.
class HudController: SKNode {
var width: CGFloat
init(gameScene:SKScene) {
width = gameScene.frame.width
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Now, when you create this object (I hope you are doing it from the scene or from a node already added to the scene otherwise we are in trouble) you simply write
class Foo : SKNode {
func foo() {
guard let scene = self.scene else { return }
let controller = HudController(gameScene: scene)
}
}
On the other hand if you are creating HudController from you scene you simply write:
class MyScene : SKScene {
override func didMoveToView(view: SKView) {
super.didMoveToView(view)
let controller = HudController(gameScene: self)
}
}
That's it.
If you want an instance property of HudController inside your GameScene this is the code.
class HudController: SKNode {
var width: CGFloat
init(gameScene:SKScene) {
width = gameScene.frame.width
super.init() // <-- do not forget this
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class GameScene: SKScene {
var hud : HudController?
override func didMoveToView(view: SKView) {
super.didMoveToView(view)
hud = HudController(gameScene: self)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With