3
votes

I have a CCSprite and a CCParticleSystemQuad that are both children of the CCLayer. In my update method, I set the emitter's position to that of the sprite, so it tracks the sprite around. The smoke puff fall out the bottom of the sprite like you'd expect and even though you move the sprite around, the smoke appears to be part of the background layer.

The problem come if I match up their rotations. Now, for example if my sprite is rocking back and forth, the puffs of smoke swing in an arc and appear attached to the sprite.

How can I make the puffs of smoke continue along the parent layer in a straight line and not rotate with the sprite? They don't translate with the sprite when I move it, so why do they rotate with it?

EDIT: adding code...

- (id)init
{
    if (!(self = [super init])) return nil;

    self.isTouchEnabled = YES;

    CGSize screenSize = [[CCDirector sharedDirector] winSize];

    sprite = [CCSprite spriteWithFile:@"Icon.png"]; // declared in the header
    [sprite setPosition:ccp(screenSize.width/2, screenSize.height/2)];
    [self addChild:sprite];

    id repeatAction = [CCRepeatForever actionWithAction:
                        [CCSequence actions:
                         [CCRotateTo actionWithDuration:0.3f angle:-45.0f],
                         [CCRotateTo actionWithDuration:0.6f angle:45.0f],
                         [CCRotateTo actionWithDuration:0.3f angle:0.0f], 
                         nil]];
    [sprite runAction:repeatAction];

    emitter = [[CCParticleSystemQuad particleWithFile:@"jetpack_smoke.plist"] retain]; // declared in the header - the particle was made in Particle Designer
    [emitter setPosition:sprite.position];
    [emitter setPositionType:kCCPositionTypeFree]; // ...Free and ...Relative seem to behave the same.
    [emitter stopSystem];
    [self addChild:emitter];

    [self scheduleUpdate];

    return self;
}


- (void)update:(ccTime)dt
{
    [emitter setPosition:ccp(sprite.position.x, sprite.position.y-sprite.contentSize.height/2)];
    [emitter setRotation:[sprite rotation]]; // if you comment this out, it works as expected.
}

// there are touches methods to just move the sprite to where the touch is, and to start the emitter when touches began and to stop it when touches end.
2

2 Answers

1
votes

I found the answer on a different site - www.raywenderlich.com

I don't know why this is true, but it seems that CCParticleSystems don't like to be rotated while you move them around. They don't mind changing their angle property. Actually, there may be cases where you want that behavior.

Anyway I made a method that adjusts the emitter's angle property and it works fine. It takes your touch location and scales the y component to be the angle.

- (void)updateAngle:(CGPoint)location
{
    float width = [[CCDirector sharedDirector] winSize].width;
    float angle = location.x / width * 360.0f;
    CCLOG(@"angle = %1.1f", angle);
    [smoke_emitter setAngle:angle]; // I added both smoke and fire!
    [fire_emitter setAngle:angle];
    //    [emitter setRotation:angle]; // this doesn't work
}
0
votes

CCSprite's anchorPoint is {0.5f, 0.5f), while the emitter descends directly from CCNode, which has an anchorPoint of {0.0f, 0.0f}. Try setting the emitter's anchorPoint to match the CCSprite's.