1

In IOS 7 with SpriteKit how do you remove a physics body only but leave the node in the scene? I am trying to allow a collision to happen and then have the car actor smash through the obstacle wall.

for (SKSpriteNode *node in _obstacles)
{
    node.position = CGPointMake(node.position.x - 2, node.position.y);

    if( [_car intersectsNode: node] && node.physicsBody.collisionBitMask == 0)
    {
        NSLog(@"We have a hit!");
        _lives--;

        //prevent simultaneous hit
        node.physicsBody.collisionBitMask = 1;
        node.physicsBody.contactTestBitMask = 1;
        node.physicsBody.dynamic = NO;

        node.physicsBody = nil;

       // [removeRequired addObject:node];
        //flash the car to show momentary invuln

        if(_lives <= 0)
        {
            _gameOver = YES;
        }
    }
    else if( (node.position.x + (node.size.width / 2)) < 0)
    {
        [removeRequired addObject:node];
    }
}

But the removal doesnt seem to be respected. I can see multiple hits occuring (for reference this code is called from the update method.

user3349312
  • 11
  • 1
  • 2

2 Answers2

1

Related: Why are didBeginContact called multiple times?

As you noticed SKPhysicsContactDelegate-didBeginContact: is called multiple times despite setting the physics body to nil. This implies multiple pixels connect at the same time during a single physics simulation in the update cycle.

I believe the SKNode-physicsBody has been copied for evaluation in the cycle, any changes you make are not honored until the next physics simulation. It may also be that the engine believes the contacts happened simultaneously and the didBeginContact calls are already queued.

Regardless the following has no effect for didBeginContact calls in the same cycle:

node.physicsBody.categoryBitMask = 0
node.physicsBody.contactTestBitMask = 0
node.physicsBody.collisionBitMask = 0
node.physicsBody = nil;

My solution is the following:

  • Set planetNode.physicsBody to nil in the first didBeginContact
  • Only react to physicsBodies with non-nil node properties

_

func didBeginContact(contact: SKPhysicsContact) {
  if let planetNode = getNodeFromContact(contact, categoryBitMask: PhysicsCategory.Planet) {
    NSLog("Planet hit")
    if let physicsBody = planetNode.physicsBody {
      physicsBody.contactTestBitMask = PhysicsCategory.None
    }
    planetNode.physicsBody = nil
    planetNode.addChild(NodeFactory.explosion())
    planetNode.runAction(SKAction.fadeOutWithDuration(0.5))

    if let shipNode = getNodeFromContact(contact, categoryBitMask: PhysicsCategory.Ship) {
      NSLog("Ship hit")
      shipNode.runAction(actionBlink())
    }
  }
}

func getNodeFromContact(contact: SKPhysicsContact, categoryBitMask: UInt32) -> SKNode? {
  if (contact.bodyA.categoryBitMask & categoryBitMask) > 0 {
    return contact.bodyA.node;
  } else if (contact.bodyB.categoryBitMask & categoryBitMask) > 0 {
    return contact.bodyB.node;
  }
  return nil
}
Community
  • 1
  • 1
gav
  • 29,022
  • 23
  • 65
  • 90
0

You could add a new node with no physicsBody at the same position as the car that just collided that has all of the same values (texture, velocity, etc...) and then simply remove the car that collided. Swap one for the other.

Scooter
  • 4,068
  • 4
  • 32
  • 47