ios - 使用所需的 init(nscoder) 时从代码设置物理体

标签 ios swift sprite-kit initialization physics

我正在尝试利用 init?(coder aDecoder: NSCoder) 函数,以便我可以在我的 sks 文件中子类化 Sprite 。

我可以在 sks 文件中设置物理体,但它不适用于我正在使用的也有圆角的矩形 sprite。由于圆角,在使用 init 函数之前,我在代码中设置了 physicsbody,并将宽度设置为略小于正方形的宽度(这样当我的英雄滑出正方形时,没有间隙圆角是..

我知道我可以使用 alpha mask physics body 来获得相同的效果,除了这个,当我的英雄在方 block 上时似乎有 1 px'ish 的差距,而且看起来不太好。

想知道为什么我不能这样设置物理体,以及我该如何做或绕过它?

感谢您的帮助!!!

更新:

    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    if let p = userData?.value(forKey: "col") as? String {
        setup(p)
        print("working")
    }
}
func setup(_ col: String) {
    setupPhysics()
    //allSprites.append(self)

在 setupPhysics 中我有:

override func setupPhysics() {
    physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: frame.width - 4, height: frame.height - 1))
...more code...
}

这是我的 Sprite 代码,我在 sks 文件中正确设置了它...

我注释掉了 allSprites 的附加部分,这样我就可以证明它不起作用。取消注释后, Sprite 被添加到 allSprites,然后在场景文件中我的 didMove 函数中,它循环遍历 allSprites 并运行 setupPhysics():

  func setup(_ col: String) {
    //setupPhysics()
    allSprites.append(self)

// scene file
    func setupAllSpritesPhysics() {
    for sprite in allSprites { sprite.setupPhysics() }
}

@Knight0fDragon:

您提到这是一个丑陋的修复程序。我不同意,因为它不会以“正确”的方式工作。目前我没有足够的 Sprite 来导致场景加载出现任何延迟。如果是这样的话,我可以在未来进行调查。

我承认我没有尝试过你提到的方法,因为我不想为我创建的每个 Sprite 创建一个子节点来解决这个问题,即使它有效。不过,我很感激到目前为止的建议。

最佳答案

为了使它与 SKS 文件一起工作,我将添加一个具有所需主体尺寸的子 SKNode,然后在自定义类代码中执行

required init(coder aDecoder:NSCoder){
    super.init(coder:aDecoder)
    if let child = childNode(withName:"child"), let physicsBody = child.physicsBody{
       self.physicsBody = physicsBody
       child.removeFromParent()
    }
}

我们在这里所做的是将物理体从子对象转移到父对象,然后杀死子对象。这使我们的代码更加动态,并使设计与功能分离。

好吧,来自 apple 的漂亮小 bug 。

发生的事情是 physicsWorld 在 NSCoder 发生时不存在,而不是在它存在时将附加到 Sprite 体的物理体放入世界中,它决定缓存位于 SKS 文件中的那个,这就是它不起作用的原因。

因此,解决这个问题的一个非常方便的方法是实现一个 worldNode(最好这样做,尤其是如果你想创建一个暂停屏幕),然后将其删除,然后在 sceneLoad 期间将其添加回去:

class GameScene: SKScene,SKPhysicsContactDelegate {
    lazy var worldNode : SKNode = { self.childNode(withName:"//worldNode")!}()

    override func sceneDidLoad() {
        worldNode.removeFromParent()
        addChild(worldNode)
    }
}

关于ios - 使用所需的 init(nscoder) 时从代码设置物理体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44533853/

相关文章:

ios - 为什么图像未显示在 Objective-C 的 cellforRowAtIndexPath 中

iOS 应用程序 - 从 POD 安装 SDK 后应用程序的大小太大

ios - 如何将 Facebook 的 Buck Build 安装到现有的 Xcode 项目中?

ios - UIView 的程序化 "fuzzy"样式背景

arrays - 对一维字符串数组进行排序

ios - 查找正在拖动的 ImageView

ios - 使用 UICollectionView 调整 UICollectionViewCell 的大小

ios - 使用 SKAction.scale 更改 Sprite 的比例

ios - 复杂的敌人行为和模式

ios - didBeginContact 未被调用