Harold
Harold

Reputation: 205

Sprite kit: remove specific node instead of all nodes

I've created an app which has a constant flow of 'stone' nodes falling from the sky, in two different sizes. The player controls a third stone object and gets points depending on which of the two falling stone types is collected. Finally, a beam object functions as a moving ground. So far, I've added collision detection in my app, which detects the collisions between the different stones and the beam. This is my collision code:

static const uint32_t stoneCategory = 1;
static const uint32_t beamCategory = 2;
static const uint32_t stoneCategory2 = 4;

and

-(void)didBeginContact:(SKPhysicsContact *)contact{

SKPhysicsBody *firstBody;
SKPhysicsBody *secondBody;

CGPoint contactPoint = contact.contactPoint;

float contact_x = contactPoint.x;
float contact_y = contactPoint.y;

if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
     firstBody = contact.bodyA;
     secondBody = contact.bodyB;
}

else
{
    firstBody = contact.bodyB;
    secondBody = contact.bodyA;
}


// First condition: make big stone stick to moving beams 
if ((firstBody.categoryBitMask & stoneCategory) != 0)
{
    SKPhysicsJointFixed *joint =
    [SKPhysicsJointFixed jointWithBodyA:contact.bodyA
                                  bodyB:contact.bodyB
                                 anchor:CGPointMake(contact_x, contact_y)];

    [self.physicsWorld addJoint:joint];
}


// Second condition: remove small stone on collision with big stone

if ((firstBody.categoryBitMask & stoneCategory) != 0 &&
    (secondBody.categoryBitMask & stoneCategory2) != 0)
{

      NSLog(@"Hit");

      [self enumerateChildNodesWithName:@"stone" usingBlock:^(SKNode *node, BOOL *stop) {
      [node removeFromParent];
  }];
}

This works perfectly as expected. When the big stone hits a beam object, it sticks to it and moves along with it. Also, when the big stone and small stone collide, the small stone is removed from the scene. However: although I understand that this is exactly what my code should do since it points to my stone method (called 'stone'), on collision between the stones, I only want that one specific small stone to be removed, and NOT all the small stones visible on the scene that moment.

I can't figure out how to make this happen. To recap: how can I remove one specific node, rather than removing it's entire method? Hope that my question is clear, I'd be happy to provide any more details if needed.

My stone method:

-(void) addStone
 {

 SKSpriteNode *stone = [[SKSpriteNode alloc] initWithColor:[SKColor grayColor] size:CGSizeMake(12, 12)];

stone.position = CGPointMake(skRand(0, self.size.width), self.size.height+12);
stone.name = @"stone";
stone.physicsBody.categoryBitMask = stoneCategory2;
stone.physicsBody.contactTestBitMask = stoneCategory;

stone.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:stone.size];
stone.physicsBody.usesPreciseCollisionDetection = YES;

[self addChild:stone];
}

And in my createSceneContents

SKAction *makeStone= [SKAction sequence:@[
                                        [SKAction performSelector:@selector(addStone) onTarget:self],
                                        [SKAction waitForDuration:0.30 withRange:0.25]
                                        ]];

 [self runAction:[SKAction repeatActionForever:makeStone]];

The above is my small stone method. For the big one, I use a comparable method but with other names to it.

Upvotes: 3

Views: 4862

Answers (3)

Jayachandra A
Jayachandra A

Reputation: 1342

Try this single line of code

[self enumerateChildNodesWithName:@"stone" usingBlock:^(SKNode *node, BOOL *stop) {
            [node removeFromParent];
        }];

Upvotes: 1

dragoneye
dragoneye

Reputation: 701

the reason behind it 1)sprite draw new objects at z order and collision also happen the order your drawing then

so when you remove a small stone at first time and recreate it changes its body from A to B

just check the specific body type on contact code below

 if(([contact.bodyA.node.name isEqualToString:@"bigstone"] && [contact.bodyB.node.name isEqualToString:@"smallstone"] ) || ([contact.bodyA.node.name isEqualToString:@"smallstone"] && [contact.bodyB.node.name isEqualToString:@"bigstone"]) )
        {


            if([contact.bodyA.node.name isEqualToString:@"smallstone"] )
            {
                [contact.bodyA.node removeFromParent];
            }else{
                [contact.bodyB.node removeFromParent];
            }

    }

Upvotes: 4

Andrey Gordeev
Andrey Gordeev

Reputation: 32449

if ((firstBody.categoryBitMask & stoneCategory) != 0 &&
    (secondBody.categoryBitMask & stoneCategory2) != 0)
{
      NSLog(@"Hit");
      [secondBody.node removeFromParent];
}

Upvotes: 0

Related Questions