2017-06-14 17 views
3

我试图利用init?(coder aDecoder:NSCoder)函数,以便我可以在sks文件中继承sprites。使用所需的init(nscoder)设置物理主体代码

我可以在sks文件中设置物理体,但是对于我使用的也有圆角的矩形精灵来说,它效果不佳。由于圆角,在使用init函数之前,我使用代码设置了物理体,并将宽度设置为略小于方形宽度(这样,当我的英雄从方块滑落时,没有间隙圆角是..

我知道我可以使用阿尔法面具物理身体得到相同的影响,除了这个,当我的英雄是在块,似乎有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... 
} 

这是我对精灵的代码,我有它正确地安装在SKS文件...

我将allSprites的附录注释掉了,这样我就可以证明它不起作用。随着追加注释掉,精灵被添加到allSprites,然后在场景文件我didMove功能,它遍历allSprites和运行setupPhysics():

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

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

@ Knight0fDragon:

您提这是一个丑陋的修复。我不同意这个事实,即它不会以'正确'的方式工作。目前我没有足够的精灵来引起场景加载的任何滞后。如果情况确实如此,我可以在未来考虑这一点。

我承认我没有尝试过你提到的方法,因为我不想为每个创建的sprite创建一个子节点,以便即使它能够正常工作。我欣赏目前为止的建议。

+0

它会帮助你,如果你显示一些更多的信息。如果英雄物理是在代码中设置的,则显示代码或显示图像,以显示当精灵进行交互时正在发生的事情。你可以提供的信息越容易找出你的问题。 –

+0

感谢您的评论,我目前没有将我的电脑放在我面前,但是当我有机会时我会更新这个问题。我可以说,init函数正常工作并且工作,我只有1个init函数。在super.init被调用后调用设置物理的函数。我确实得到它太工作,使用完成关闭的等待skaction ...所以我认为super.init需要更多的时间完成,但这似乎有点hacky ... – Discoveringmypath

+0

你甚至检查,看看是否打印线正在发生 – Knight0fDragon

回答

4

为了与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() 
    } 
} 

我们在这里做的是将物理体从小孩转移到父母,然后杀死孩子。这使我们的代码变得更加动态一些,并保持设计与功能的分离。

嗯,来自苹果的漂亮的小虫子。

发生的事情是在NSCoder发生的时候物理世界并不存在,而是在它存在的时候将附着在物体上的物理体放入世界中,它决定缓存位于SKS文件中的物体,这就是为什么它不起作用。

所以解决这个问题的一个非常方便的方法是实现一个worldNode(无论如何这是一个很好的做法,特别是如果你想创建一个暂停屏幕),只需删除它,然后将其添加回sceneLoad:

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

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

感谢您的回复。我将不得不尝试这...我的印象是super.init需要更多时间才能完成设置物理主体,如果您阅读我上面的评论...所以我有点怀疑这会起作用,但是谁知道......我最终确定了一个修补程序。我将所有我感兴趣的精灵存储在一个数组中......所以我在游戏场景文件中添加了一个函数来循环访问数组并运行设置物理。我在didmove函数结束时调用了函数,一切都很好......您如何看待这个解决方案? – Discoveringmypath

+0

没有任何东西在后台线程上运行,super.init完成后,你的精灵已经准备好了 – Knight0fDragon

+0

这是一个非常难看的解决方案,如果你有很多精灵,你最终会导致你的游戏暂时冻结。 – Knight0fDragon