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;... }
source to share
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)
andif (self.shieldIsActive)
will always betrue
(unlessshieldIsActive
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;
}];
}
source to share
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.
source to share