Preventing sprite nodes from stacking on top of each other?

I am trying to create a shield guard for my iOS spritekit, instead of updating the current screen, it puts another shield on top. My code:

    - (void) didMoveToView: (SKView *) view {
               ...
    self.shieldIsActive = NO;
               ...
}
    - (void) didBeginContact: (SKPhysicsContact *) contact {
               ...
   else if (firstBody.categoryBitMask == CollisionCategoryLaser | firstBody.categoryBitMask == CollisionCategoryPlasmaShot | firstBody.categoryBitMask == CollisionCategoryProjectile && secondBody.categoryBitMask == CollisionCategoryShieldIcon) {
        // Projectile OR Plasma Shot Or Laser hits Shield Icon
        ShieldIconNode * shieldIcon = (ShieldIconNode *) secondBody.node;
        ShieldNode * shield = [ShieldNode shieldAtPosition: CGPointMake (CGRectGetMidX (self.frame) +4, CGRectGetMidY (self.frame) -210)];
        [shieldIcon removeFromParent];
        if (firstBody.categoryBitMask == CollisionCategoryProjectile) {
            ProjectileNode * projectile = (ProjectileNode *) firstBody.node;
            [projectile removeFromParent];
        }
        if (! self.shieldIsActive) {
            [self addChild: shield];
            self.shieldIsActive = YES;
        }
        // Remove shield after a period of time. BUG: Adds multiple shields if one is already active
        if (self.shieldIsActive) {
            SKAction * wait = [SKAction waitForDuration: ShieldTimer];
            [self runAction: wait completion: ^ {[shield removeFromParent];}];
            self.shieldIsActive = NO;

               ...
    }

      

+3


source to share


2 answers


As Domsware pointed out, the bitwise |

must be replaced with a boolean ||

(and matching parentheses appended) in your first statement if

. Oddly enough, since the operator |

has a lower precedence than the operator ==

, your operator if

may have worked as you expected.

Also, you should consider hiding / showing the screen instead of adding / removing shields as Whirlwind suggested.

However, some thoughts ...



  • The conditions for if (!self.shieldIsActive)

    and if (self.shieldIsActive)

    will always be true

    (unless shieldIsActive

    specified elsewhere in the code), which can result in more than one screen in the scene at a time
  • Moving self.shieldIsAction = NO

    to the action completion block will solve this problem.

and some code ...

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

      

+4


source


Let's replace this condition:

else if (firstBody.categoryBitMask == CollisionCategoryLaser | firstBody.categoryBitMask == CollisionCategoryPlasmaShot |firstBody.categoryBitMask == CollisionCategoryProjectile && secondBody.categoryBitMask == CollisionCategoryShieldIcon){

      

:



else if ((firstBody.categoryBitMask == CollisionCategoryLaser || firstBody.categoryBitMask == CollisionCategoryPlasmaShot || firstBody.categoryBitMask == CollisionCategoryProjectile ) && secondBody.categoryBitMask == CollisionCategoryShieldIcon){

      

Note the use of ||

instead |

for the OR operator.

+4


source







All Articles