iphonecocos2d-iphoneccparticlesystem

Using particle effects in cocos2d with ccspritebatchnode


I'm trying to add a particle effect to my cocos2d iOS game. I'm having a problem when adding particles to my sprites because all of my sprites are using a spritebatch for improved performance. It seems I can't easily use a particle effect on my sprites because of this. Everything works correctly if I simply keep all particle effects on my gameplay layer, but I'd rather have each sprite keep track of its own particle effect. Here is my code, which is located in my player class:

-(void)loadParticles  
{    
    shieldParticle = [[CCParticleSystemQuad alloc] initWithFile:@"shieldParticle.plist"];
    shieldParticle.position = self.position;
    [self addChild:shieldParticle];  
}

Using this technique gives me an error saying

CCSprite only supports CCSprites as children when using CCSpriteBatchNode

To avoid this, I made a separate class, particleBase.

In the particleBase class I inherit it from ccsprite and have an iVar for tracking the particle effect:

#import "cocos2d.h"
@interface particleBase : CCSprite
{
CCParticleSystem *particleEffect;
}

-(void)setParticleEffect:(NSString *)effectName;
-(void)turnOnParticles;
-(void)turnOffParticles;
@end

#import "particleBase.h"

@implementation particleBase

-(void)setParticleEffect:(NSString *)effectName
{    
    particleEffect = [[CCParticleSystemQuad alloc] initWithFile:effectName];
    particleEffect.active = YES;
    particleEffect.position = self.position;
    [self addChild:particleEffect];
}

When using this technique I tried this in my player class:

-(void)loadParticles
{    
    shieldParticle = [[particleBase alloc] init];
    [shieldParticle setParticleEffect:@"shieldParticle.plist"];
    [shieldParticle turnOnParticles];
    [shieldParticle setPosition:self.position];
    [self addChild:shieldParticle z:150];      
}

When doing this I don't receive an error, but the particle isn't displayed either.

Any help would be greatly appreciated.


Solution

  • Add an instance variable for the particle system in your sprite class. Then, when you create the particle effect, don't add it to the sprite itself but some higher level node. This could be the main game layer or scene, or you could simply use self.parent.parent which would give you the sprite batch node's parent.

    Then schedule an update method in the sprite class. If the particle system isn't nil, set its position to the position of the sprite. Plus offset if need be.

    Et voilá:

    -(void) createEffect
    {
        particleSystem = [CCParticleSystem blablayouknowwhattodohere];
        [self.parent.parent addChild:particleSystem];
        particleSystem.position = self.position;
    
        // if not already scheduled:
        [self scheduleUpdate];
    }
    
    -(void) removeEffect
    {
        [particleSystem removeFromParentAndCleanup:YES];
        particleSystem = nil;
    
        // unschedule update unless you need update for other things too
        [self unscheduleUpdate];
    }
    
    -(void) update:(ccTime)delta
    {
        if (particleSystem)
        {
            particleSystem.position = self.position;
        }
    }