SKSpriteNode subclass: method to remove all joints
Asked Answered
R

1

7

I have created a subclass of SKSpriteNode. I connect instances of that class together with joints of type SKPhysicsJointLimit. I do this within my didEndContact(contact: SKPhysicsContact) in my GameScene:

var joint = SKPhysicsJointLimit.jointWithBodyA(contact.bodyA, bodyB: contact.bodyB, anchorA: pos1!, anchorB: pos2!)
self.physicsWorld.addJoint(joint)

This works well so far. Then i come to the point where i want to release the node from the joint. According to the SKPhysicsBody docs there is a property called "joints" which is an array holding SKPhysicsJoint objects. I thought thats exactly what I need, but I am not able to iterate over an instance's joints and remove them from the physicsWorld. To do the job i added a method to my custom SKSpriteNode subclass.

func freeJoints(world: SKPhysicsWorld){
        if let joints = self.physicsBody?.joints {
            for joint in joints{
                println("found a joint: \(joint)")
                // example print:
                //found a joint: <PKPhysicsJointRope: 0x7fbe39e95c50>
                world.removeJoint(joint as SKPhysicsJoint)
            }
        }
    }

Calling the method fails after the println() statement with the message "Swift dynamic cast failed". I would really appreciate your opinion in how to work with an SKPhysicsBody's joint property. More specifically: How to use (cast?) the items in the array to be able to remove them from a scene's SKPhysicsWorld.

Rotor answered 25/12, 2014 at 17:29 Comment(2)
If i remember correctly the joints array holds the internal PKPhysicsJoint instances so the casting will fail, because SKPhysicsJoint is just a convenience class to create the actual joint instances. Not sure how to resolve this with swift, in objc it will just allow you to cast to skphysicsjoint or id. But it seems you only need a way to cast the joints in a way swift won't complain about.Westmorland
@LearnCocos2D You are right. The joints array holds PKPhysicsJoint objects. Even though the documentation says it "holds an array of SKPhysicsJoint objects". For objective-c I found a tutorial that solves a similar problem (as you said), by casting the joint-array-items and removing them from the physics-world. Interestingly the same tutorial existst in a "how to do it with swift"-version that uses another approach.Rotor
R
3

I spent a little more time in investigating this. This is what I have come up with:

I decided to add an property to my SKSpriteNode subclass and manage the joints myself

    var joints: [SKPhysicsJointLimit]
override init(){
    ...
    self.joints = []
    ...
}

Everytime I add an joint to the scene's SKPHysicsWorld I also add it to the joints array of the SKNNode itself. Whilst iterating the SKPHysicsBody's joints-Array failed (see question) at the point I wanted to cast it to SKPhysicsJoint, removing items from the physics world works as intended when iterating the array of SKPhysicsJointLimit items:

func freeJoints(world: SKPhysicsWorld){
        for item in self.joints{
            println("removing item from physics world \(item)")
            world.removeJoint(item)
        }
        self.joints.removeAll(keepCapacity: false)
    }
}

This seems not to be the most elegant way to do the job, since there already is a framework managed array that promises to be same thing. But I was unable to utilize it and this works for now.

Rotor answered 26/12, 2014 at 0:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.