你如何在自定义类中获得GameScene的frame.width?

时间:2015-10-10 14:03:31

标签: swift sprite-kit

我在尝试将GameScene的 frame.width 变成自定义类时遇到了麻烦,因为我需要在我的自定义类init中定位节点的场景宽度。

HudController.swift片段

import SpriteKit

    class HudController:SKNode {
        var width:CGFloat

        override init(){
            width = GameScene().frame.width //I was hoping to add the scene width here
        }
    }

以下代码在我身上崩溃,我尝试了大量其他解决方案但没有成功。

有人可以帮我解决这个问题吗?

谢谢!

更新后的代码===

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")
    }
}

1 个答案:

答案 0 :(得分:7)

SpriteKit中的每个节点都可以使用scene属性检索它所在的场景。

let node = SKNode()
node.scene

scene属性返回SKScene?,值为可选,因为如果当前节点不属于某个场景,当然也没有要检索的场景

现在,您可能想在self.scene的初始值设定项中使用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")
    }
}

但它现在可以正常工作,因为在初始化super.init属性之前无法调用width

很好,那你可以尝试一下。

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")
    }
}

再次编译错误,因为您在调用self之前使用super.init()

最后还有一个问题,当执行初始化程序时,正在创建的节点还没有父节点,因此self.scene属性确实返回nil

如何解决这个问题?

解决方案

首先声明初始化程序接收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")
    }
}

现在,当你创建这个对象时(我希望你是从场景或已经添加到场景中的节点进行的,否则我们遇到了麻烦)你只需要编写

class Foo : SKNode {

    func foo() {
        guard let scene = self.scene else { return }
        let controller = HudController(gameScene: scene)
    }
}

另一方面,如果你从你的场景创建HudController,你只需写:

class MyScene : SKScene {

    override func didMoveToView(view: SKView) {
        super.didMoveToView(view)
        let controller = HudController(gameScene: self)
    }
}

就是这样。

更新

如果你想在GameScene里面有一个HudController的实例属性,这就是代码。

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)
    }
}