0

I'm re-using the approach used in DemoBots for contact detection. I've come across a problem because of a difference between how my code works and how DemoBots is written. In DemoBots, the component RenderComponent has a variable 'node'

let node = EntityNode()

init(entity: GKEntity) {
    node.entity = entity
}

In my code, I'm not using animations, so my equivalent of RenderComponent is a bit more complex. The variable 'node' is already used and tied to the physicsBody, so I've created a new variable 'entityNode'

let node: SKSpriteNode
let entityNode = EntityNode()

init(entity: GKEntity, nodeTemplate: SKSpriteNode) {
    node = SKSpriteNode(imageNamed: "animal")
    entityNode.entity = entity
}

Within the handleContact: method, I've tried two solutions to get the reference to the entity. Option 1:

let entityA = (contact.bodyA.node as? EntityNode)?.entity
let entityB = (contact.bodyB.node as? EntityNode)?.entity

Running a print() check on this returns a nil value for these two entities. That's logical enough as I should look for a property named 'entityNode' to find the entity. When I change it to Option 2:

let entityA = (contact.bodyA.entityNode as? EntityNode)?.entity
let entityB = (contact.bodyB.entityNode as? EntityNode)?.entity

I get an error that the physicsBody doesn't have a member 'entityNode.' I've tried a bunch of other things like looking up the entity associated with the contactBody, but I get another error which says the subsequent code is looking for an optional. I've tried getting rid of the 'if' but it just moves the problem along to the next contactCallBack call.

if let notifiableEntity = entityA as? ContactNotifiableType, otherEntity = entityB where aWantsCallback {
    contactCallback(notifiableEntity, otherEntity)
}

Any ideas how I can resolve this to get the contactCallBack call working?

Shane O'Seasnain
  • 3,534
  • 5
  • 24
  • 31

2 Answers2

0

Option 1 should work fine if the colliding node(s) is/are of an Entity Component that has a node of type EntityNode. You create an EntityNode class

class EntityNode: SKSpriteNode {
    weak var entity: GKEntity!
}

Your RenderComponent should be something like this:

class RenderComponent: GKComponent{

let node: EntityNode

init(entity:GKEntity, ......) {
    node = EntityNode(texture: texture, color: SKColor.whiteColor(), size: size)
    node.physicsBody = SKPhysicsBody(rectangleOfSize: aCGSize, center: aCGPoint)

    node.physicsBosy.categoryBitMask = PhysicsCat.Enemy
}

The initialization of node is using EntityNode but with any init of SKSpriteNode you like.

Finally, within the contactCallBack "didBeginContact or didEndContact", your option1 will work if the contact.body(A or B).categoryBitMask is = to PhysicsCat.Enemy

something like this:

if (contact.bodyA.categoryBitMask == PhysicsCat.Enamy || contact.bodyB.categoryBitMask == PhysicsCat.Enamy) {
    let entityA = (contact.bodyA.node as? EntityNode)?.entity
    let entityB = (contact.bodyB.node as? EntityNode)?.entity
    ...
}

Your option 2 will never work because the contact.bodyA and bodyB both has property node of type SKNode which you have to cast first to EntityNode as in option 1

AZZADEEN
  • 1
  • 3
-1

I recently came across similar problem - make sure your iOS version is >= 9 and OSX at least 10.11

ziemien
  • 1
  • 3