user5177178
user5177178

Reputation:

-[SKScene didBeginContact] executing multiple times

I'm creating a shield power up for my game. The way it works is if you shoot a power up icon, you gain a shield that expires over time. When a rock hits the shield it gets destroyed creating debris. The problem that occurs is that over the course of the game when you hit multiple shield icons, the amount of debris that is created is increased significantly. It's as if there are multiple shields when there is only one. How do I fix this?

My Code: 
- (void) didBeginContact:(SKPhysicsContact *)contact{
         ...
    else if (firstBody.categoryBitMask == CollisionCategoryRocks && secondBody.categoryBitMask == CollisionCategoryShield){
        // Rock hits Shield
        if (!_shield.hidden){
            if (firstBody.categoryBitMask == CollisionCategoryRocks){
                SpaceRockNode *spaceRock = (SpaceRockNode *) firstBody.node;
                [spaceRock removeFromParent];
                [self createDebrisAtPosition:contact.contactPoint];
            } 
        }
    }

    else if ((firstBody.categoryBitMask == CollisionCategoryLaser || firstBody.categoryBitMask == CollisionCategoryPlasmaShot ||firstBody.categoryBitMask == CollisionCategoryProjectile) && secondBody.categoryBitMask == CollisionCategoryShieldIcon){
    // Projectile hits Shield Icon

        if (!self.shieldIsActive){
            self.shield = [ShieldNode shieldAtPosition:CGPointMake(CGRectGetMidX(self.frame)+4, CGRectGetMidY(self.frame)-210)];
            [self addChild:self.shield];
            self.shieldIsActive = YES;
            SKAction *wait = [SKAction waitForDuration:ShieldTimer];
            [self runAction:wait completion:^{
               self.shield.hidden = YES;
               self.shieldIsActive = NO;
            }];
       }
   }
           ...
}

Upvotes: 0

Views: 80

Answers (1)

DDPWNAGE
DDPWNAGE

Reputation: 1443

Your problem is, 2 collisions are happening when debris flies out like crazy:

  1. Space Rock X and Shield 1
  2. Space Rock X and Shield 2

This causes didBeginContact: to be called twice, and so, you have twice as much debris flying out.

One thing I would fix, just to shorten your code a bit, is to change this statement...

SpaceRockNode *spaceRock = (SpaceRockNode *) firstBody.node;
[spaceRock removeFromParent];

into...

[firstBody.node removeFromParent];

If you don't do anything else with that Space Rock, then there's no reason to make the node into a space rock just to use it as a node.


Next, turn this if statement...

if (!self.shieldIsActive) {
    ...
}

into...

if (!self.shieldIsActive && ![self.children containsObject:self.shield]) {
    ...
}

This modified statement makes sure self.shield is a member of self.children before adding self.shield to self.children a second time. If there's only one shield, only one bunch of debris will fly out.

If self.shield is set to nil (in other words, it hasn't been assigned to yet), the containsObject: method will evaluate to NO because self.children doesn't contain nil. Xcode will actually break with an exception if you try and add a nil node. Therefore, if self.shield is nil, that expression will always evaluate to NO.

Upvotes: 1

Related Questions