ETRunner
ETRunner

Reputation: 13

Loading Physics Body for Subclasses of SKSpriteNode

Is there a way to load a physics body as a subclass of an SKSpriteNode? I created a subclass of an SKSpriteNode outside the scene.

class specializedNode: SKSpriteNode {
    var variable = 0
}

Inside the scene, I created a function that creates objectA and a structure for the physics categories.

struct PhysicsCategory {
    static let None : UInt32 = 0
    static let All  : UInt32 = UInt32.max
    static let A    : UInt32 = 0b1      
    static let B    : UInt32 = 0b10     
}

func spawnObjectA () {
    objectA = specializedNode()

    objectA.physicsBody = SKPhysicsBody(rectangleOfSize: objectA.size)
        objectA.physicsBody?.dynamic = true
        objectA.physicsBody?.categoryBitMask = PhysicsCategory.A
        objectA.physicsBody?.contactTestBitMask = PhysicsCategory.B
        objectA.physicsBody?.collisionBitMask = PhysicsCategory.None
        objectA.physicsBody?.usesPreciseCollisionDetection = true
    addChild(objectA)
}

Then, I called didBeginContact for when objectA collides with objectB.

func objectADidCollide(objectA:specializedNode, objectB:SKSpriteNode) {
    objectB.removeFromParent()
    ++objectA.variable
}

func didBeginContact(contact: SKPhysicsContact) {
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if ((firstBody.categoryBitMask & PhysicsCategory.A != 0) && (secondBody.categoryBitMask & PhysicsCategory.B != 0)) {
            objectADidCollide(firstBody.node as specializedNode, objectB: secondBody.node as SKSpriteNode)
    }
}

However, when I run the code and the two objects collide, the code hits a breakpoint and the debug navigator pops up.

Line 10 (0x58e0fc: trap) turns green and displays:

"Thread: 1 EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)"

libswiftCore.dylib`swift_dynamicCastClassUnconditional:
0x58e0ec:  cbz    r0, 0x58e0fc              ; swift_dynamicCastClassUnconditional + 16
0x58e0ee:  ldr    r2, [r0]
0x58e0f0:  cmp    r2, r1
0x58e0f2:  it     eq
0x58e0f4:  bxeq   lr
0x58e0f6:  ldr    r2, [r2, #0x4]
0x58e0f8:  cmp    r2, #0x0
0x58e0fa:  bne    0x58e0f0                  ; swift_dynamicCastClassUnconditional + 4
0x58e0fc:  trap   
0x58e0fe:  nop 

I do not want to load objectA as an SKSpriteNode, as I want to change an attribute of objectA that I created in its subclass. Any suggestions?

Upvotes: 1

Views: 209

Answers (1)

stevenpaulr
stevenpaulr

Reputation: 306

I was having an almost identical problem. I started with code from a Ray Wenderlich tutorial and started subclassing from there. Well, I'm pretty sure that the tutorial swaps the projectile and the monster in didBeginContact. Since they're the same class, and it just removes them both, it didn't matter.

In your program (and mine) that means you're trying to typecast an object into something that it isn't.

I just switched firstBody and secondBody in the call to objectADidCollide and it fixed my problems.

Looking at your code, I don't think that's exactly your problem, but I wouldn't be surprised if you're typecasting the wrong object.

Upvotes: 1

Related Questions