whfissler
whfissler

Reputation: 1

Xcode 5.0.2 - Attempted to add a SKNode which already has a parent: <SKEmitterNode>

I am attempting to add a particle effect in the touchesBegan method, so when the user touches the drawn sprite(SKSpriteNode), it draws the particle effect. However, I receive an error Attempted to add a SKNode which already has a parent: SKEmitterNode. To add some context... The game is of the bejeweled/candy crush style where blocks(deleteNode) are deleted based upon neighboring colors. In the touch event I iterate recursively, checking neighboring blocks and add them to an array to later be removed. Prior to each block(deleteNode) being removed I would like the particle event to occur. They both inherit from SKNode (right?), so I don't understand the conflict...

@interface
{
   NSString *blockParticlePath;
   SKEmitterNode *blockParticle;
}

in the initialization method...

blockParticlePath = [[NSBundle mainBundle] pathForResource:@"blockParticle" ofType:@"sks";
blockParticle = [NSKeyedUnarchiver unarchiveObjectWithFile:blockParticlePath];

in touchesBegan...

blockParticle.position = deleteNode.position;
blockParticle.particleColor = deleteNode.color;
[self addChild:blockParticle];

To make sure I wasn't crazy, I checked other forums and have seen this same logic for adding particle effects to a scene. Thanks in advance. If you need any more info let me know.

Upvotes: 0

Views: 1005

Answers (1)

MB_iOSDeveloper
MB_iOSDeveloper

Reputation: 4208

@whfissler, you explanations helped a lot to pinpoint this solution.

This error occurred only when I had many SKSpriteNodes active (ballon game). On each ballon click it pops and a SKEmitterNode (explosion) is added. It seems that when the particles created by the explosion touch each other I recieve the same error like you. I changed my code from:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    SKEmitterNode *explosion = [SKEmitterNode orb_emitterNamed:@"ballonEksplosion"];
    CGPoint positionInScene = [touch locationInNode:self];
    explosion.position = positionInScene;
    SKSpriteNode *touchedSprite;
    for ( int i = 0; i < [[self nodesAtPoint:positionInScene] count]; i++)
    {
        touchedSprite = (SKSpriteNode *)[[self nodesAtPoint:positionInScene] objectAtIndex:i];
        if ([touchedSprite.name isEqualToString:@"BALLON"])
        {


            [(MBDBallon *)touchedSprite popAndRemoveWithSoundEffect];
            [self addChild:explosion];
        }
    }
}

to:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];
    SKSpriteNode *touchedSprite;
    for ( int i = 0; i < [[self nodesAtPoint:positionInScene] count]; i++)
    {
        touchedSprite = (SKSpriteNode *)[[self nodesAtPoint:positionInScene] objectAtIndex:i];
        if ([touchedSprite.name isEqualToString:@"BALLON"])
        {
            SKEmitterNode *explosion = [SKEmitterNode orb_emitterNamed:@"ballonEksplosion"];
            explosion.position = positionInScene;
            [(MBDBallon *)touchedSprite popAndRemoveWithSoundEffect];
            [self addChild:explosion];
        }
    }
}

and it worked. To me it seems that my explosion SKEmitterNode had been kept somehow to long on the SKScene and therefore adding another SKEmitterNode for the currentPosition lead to problems with the:

self nodesAtPoint:positionInScene

nodesAtPoint stack.

I don´t understand it fully, maybe this helps you in further understanding.

Upvotes: 0

Related Questions