¿Cómo se elimina una CAEmitterLayer cuando finaliza la vida útil de sus CAEmitter Cells, en lugar de repetirla hasta que se elimine de la supercapa?

Estoy usando código genérico (de la demostración de iOS Fireworks) de una manera ligeramente modificada. Tengo lo siguiente en una subclase de UIView. Lo que quiero es hacer que los fuegos artificiales aparezcan en el punto que el usuario toca (no con fuerza) y que se reproduzcan durante toda la vida útil de CAEmitterLayer / CAEmitterCells. En cambio, esto comienza inmediatamente cuando lo agrego a addSublayer, como estoy seguro de que debe hacerlo. Sin embargo, me gustaría usarlo de una manera ligeramente diferente. ¿Hay alguna manera de que pueda cambiar esto para que haya una CATransaction con un bloque de finalización (para eliminarFromSuperlayer) o algo así? Cualquier idea es bienvenida.

 #import "FireworksView.h"

    @implementation FireworksView

 - (void)launchFirework{

    //Load the spark image for the particle

    CAEmitterLayer *mortor = [CAEmitterLayer layer];
    mortor.emitterPosition = CGPointMake(self.bounds.size.width/2, self.bounds.size.height*(.75));
    mortor.renderMode = kCAEmitterLayerAdditive;

    //Invisible particle representing the rocket before the explosion
    CAEmitterCell *rocket = [CAEmitterCell emitterCell];
    rocket.emissionLongitude = -M_PI / 2;
    rocket.emissionLatitude = 0;
    rocket.lifetime = 1.6;
    rocket.birthRate = 1;
    rocket.velocity = 400;
    rocket.velocityRange = 100;
    rocket.yAcceleration = 250;
    rocket.emissionRange = M_PI / 4;
    rocket.color = CGColorCreateCopy([UIColor colorWithRed:.5 green:.5 blue:.5 alpha:.5].CGColor);
    rocket.redRange = 0.5;
    rocket.greenRange = 0.5;
    rocket.blueRange = 0.5;

    //Name the cell so that it can be animated later using keypath
    [rocket setName:@"rocket"];

    //Flare particles emitted from the rocket as it flys
    CAEmitterCell *flare = [CAEmitterCell emitterCell];
    flare.contents = (id)[UIImage imageNamed:@"tspark.png"].CGImage;
    flare.emissionLongitude = (4 * M_PI) / 2;
    flare.scale = 0.4;
    flare.velocity = 100;
    flare.birthRate = 45;
    flare.lifetime = 1.5;
    flare.yAcceleration = 350;
    flare.emissionRange = M_PI / 7;
    flare.alphaSpeed = -0.7;
    flare.scaleSpeed = -0.1;
    flare.scaleRange = 0.1;
    flare.beginTime = 0.01;
    flare.duration = 0.7;

    //The particles that make up the explosion
    CAEmitterCell *firework = [CAEmitterCell emitterCell];
    firework.contents = (id)[UIImage imageNamed:@"tspark.png"].CGImage;
    firework.birthRate = 9999;
    firework.scale = 0.6;
    firework.velocity = 130;
    firework.lifetime = 2;
    firework.alphaSpeed = -0.2;
    firework.yAcceleration = 80;
    firework.beginTime = 1.5;
    firework.duration = 0.1;
    firework.emissionRange = 2 * M_PI;
    firework.scaleSpeed = -0.1;
    firework.spin = 2;

    //Name the cell so that it can be animated later using keypath
    [firework setName:@"firework"];

    //preSpark is an invisible particle used to later emit the spark
    CAEmitterCell *preSpark = [CAEmitterCell emitterCell];
    preSpark.birthRate = 80;
    preSpark.velocity = firework.velocity * 0.70;
    preSpark.lifetime = 1.7;
    preSpark.yAcceleration = firework.yAcceleration * 0.85;
    preSpark.beginTime = firework.beginTime - 0.2;
    preSpark.emissionRange = firework.emissionRange;
    preSpark.greenSpeed = 100;
    preSpark.blueSpeed = 100;
    preSpark.redSpeed = 100;

    //Name the cell so that it can be animated later using keypath
    [preSpark setName:@"preSpark"];

    //The 'sparkle' at the end of a firework
    CAEmitterCell *spark = [CAEmitterCell emitterCell];
    spark.contents = (id)[UIImage imageNamed:@"tspark.png"].CGImage;
    spark.lifetime = 0.05;
    spark.yAcceleration = 250;
    spark.beginTime = 0.8;
    spark.scale = 0.4;
    spark.birthRate = 10;

    preSpark.emitterCells = [NSArray arrayWithObjects:spark, nil];
    rocket.emitterCells = [NSArray arrayWithObjects:flare, firework, preSpark, nil];
    mortor.emitterCells = [NSArray arrayWithObjects:rocket, nil];

    [self.layer addSublayer:mortor];
        }

preguntado el 10 de marzo de 12 a las 02:03

Me gustaría saber esto también. -

2 Respuestas

La respuesta a esto es, usando CAEmitter, NO HAY MANERA (delegado, etc.) de detener el emisor cuando finaliza el ciclo. Lo único que puede hacer es quitarlo elegantemente de la capa cuando crea que debería quitarlo.

respondido 22 mar '12, 18:03

Ok, pude lograr esto creando una animación con el delegado que se disparó junto con el emisor. en animationDidStop hice un bucle for que pasó por mi jerarquía de vistas, busqué emisores y los eliminé. tiene errores y todavía quiero una solución real, pero esto funciona por ahora.

for (CALayer *layer in _plusButton.layer.sublayers) {
    if (layer.class == [CAEmitterLayer class]) {
        [layer removeFromSuperlayer];
    }

}

respondido 11 mar '12, 14:03

No entiendes mi punto, supongo. ¿Cómo se CUENTA cuando el emisor ha llegado al final del ciclo? :) - Jann

Esa es la cuestión, tampoco puedo entenderlo, estaba buscando la respuesta y encontré tu pregunta y pensé en publicar mi solución. - Weston

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.