Setting up the physical body from code when using the required init (nscoder)

Am I trying to use the init function? (coder aDecoder: NSCoder) so that I can subclass the sprites in my sks file.

I can set the physical body to the sks file, but it doesn't work very well with my rectangular sprites I am using, which also have rounded corners. Due to the rounded corners, before using the init function, I set up the physical body in the code and set the width slightly less than the width of the squares (so when my hero slides off the square, there is no break where the rounded corner is ...

I know I can use the physical body of an alpha mask in order to get the same effect, except with this one. There seems to be 1 pixel gap when my hero is on blocks and it doesn't look very good.

I wonder why I can't establish a physical body, and also how can I do this or bypass it?

Thanks for any help !!!

Update:

    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)

      

In setupPhysics I have:

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

      

This is my code for the sprite and I configured it correctly in the sks file ...

I commented adding to allSprites to demonstrate that it doesn't work. With the uncommented added, the sprites are added to allSprites and then to my didMove function in the Scene file, it goes through allSprites and runs setupPhysics ():

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

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

      

@ Knight0fDragon:

You mentioned that this is an ugly fix. I disagree that it won't work in the "correct" way. And I currently don't have enough sprites to cause any lag in scene loading. I can look into this in the future if so.

I admit that I haven't tried the method you talked about because I don't want to create a child node for every sprite I create to get around this even if it works. I appreciate the advice so far, though.

+3


source to share


1 answer


To make this work with the SKS file, I would add a child SKNode with the dimensions of the body you want, and then in the custom class code do

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

      

What we are doing here is transferring the physical body from the child to the parent, and then killing the child. This allows our code to be a little more dynamic and keeps the design separate from the functionality.

Well, cute little apple bug.



What's happening is physics. The world doesn't exist for the time the NSCoder happens and instead of putting the physics body in the sprite body in the world when it does, it decides to cache the one in the SKS file and so it doesn't work.

So a very convenient way to get around this problem is to implement worldNode (it's good to do this anyway, especially if you want to create a pause screen), and just remove it and then add it back during sceneLoad

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

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

      

+5


source







All Articles