2012-07-11 14 views
39

Estoy tratando de establecer un CAEmitterLayer para hacer un efecto confeti, y me he encontrado con dos problemas:CAEmitterLayer emite partículas no deseados al azar en eventos de toque

  1. Cada vez que me puse la birthRate en mis células para algo diferente de cero para comenzar la animación obtengo una ráfaga de celdas colocadas al azar en la pantalla, que se animan normalmente, y luego el emisor continúa emitiendo correctamente después de eso.
  2. Cada vez que el emitterCells dibuja cosas en la pantalla, cada vez que toco la pantalla, el emisor dibuja emitterCells en (al parecer) ubicaciones al azar que existen durante un tiempo (aparentemente) aleatorio. Nada en el emisor está vinculado a ningún evento táctil (es decir, no estoy dibujando intencionadamente nada en un evento táctil), pero la capa está en una vista que tiene múltiples vistas incrustadas. Cuanto más toco, más células aparecen.

Aquí está mi código para configurar el emisor, y luego arrancar y parar que (una vez que he llamado la función de parada, a continuación, toca el cese pantalla de creación de nuevos elementos al azar):

- (void)setupConfetti 
{ 
    self.confettiLayer = [CAEmitterLayer layer]; 
    [self.view.layer addSublayer:self.confettiLayer]; 
    [self.view.layer setNeedsDisplay]; 

    self.confettiLayer.emitterPosition = CGPointMake(1024.0/2,-50.0); 
    self.confettiLayer.emitterSize = CGSizeMake(1000.0, 10.0); 
    self.confettiLayer.emitterShape = kCAEmitterLayerLine; 
    self.confettiLayer.renderMode =kCAEmitterLayerUnordered; 

    CAEmitterCell *confetti = [CAEmitterCell emitterCell]; 

    confetti1.contents = (id)[[UIImage imageNamed:@"confetti.png"] CGImage]; 

    confetti.emissionLongitude = M_PI; 
    confetti.emissionLatitude = 0; 
    confetti.lifetime = 5; 
    confetti.birthRate = 0.0; 
    confetti.velocity = 125; 
    confetti.velocityRange = 50; 
    confetti.yAcceleration = 50; 
    confetti.spin = 0.0; 
    confetti.spinRange = 10; 
    confetti.name = @"confetti1"; 

    self.confettiLayer.emitterCells = [NSArray arrayWithObjects:confetti, nil]; 
} 

para iniciar el confeti:

- (void)startConfettiAnimation 
{ 
    [self.confettiLayer setValue:[NSNumber numberWithInt:10.0] forKeyPath:@"emitterCells.confetti.birthRate"]; 
} 

Y para detenerlo:

- (void)stopConfettiAnimation 
{ 
    [self.confettiLayer setValue:[NSNumber numberWithInt:0.0] forKeyPath:@"emitterCells.confetti.birthRate"]; 
} 

Nuevamente, una vez que se inicia, después de la ráfaga inicial de elementos aleatorios, esto funciona bien: todo se anima normalmente, y cuando birthRate se pone a cero, finaliza con gracia. Simplemente parece responder a eventos táctiles, y no tengo idea de por qué. Intenté agregar el emitterLayer a una vista diferente, inhabilitar la interacción del usuario en esa vista y luego agregarla como una subvista de la vista principal, y eso no pareció funcionar.

¡Cualquier ayuda/idea sería muy apreciada!

Gracias, Sam

+4

¿Has descubierto algo sobre esto? Estoy teniendo el mismo problema también. Parece una "característica" muy innecesaria para mí. –

+4

¿Quizás después de un año desde el último comentario en esta publicación, alguien encontró la solución a este problema? Veo este problema en cada proyecto fundado en la web que usa la clase CAEmitterLayer. Puedes probar incluso con este tutorial: http://www.raywenderlich.com/6063/uikit-particle-systems-in-ios-5-tutorial. Simplemente elimine el manejo de toques de vc y reduzca birthRate a 1, por ejemplo, y comience a grabar en cualquier lugar. Parece que todas las partículas vivas se duplicaron después del toque. El problema aparece solo en los dispositivos, no en el simulador. –

Respuesta

1

Podría ser que usted no está mirando para ver si la partícula está emitiendo como en el ejemplo Wenderlich Artur Ozieranski publicado? No estoy viendo el doble mientras el cheque esté en su lugar.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [fireView setEmitterPositionFromTouch: [touches anyObject]]; 
    [fireView setIsEmitting:YES]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    [fireView setIsEmitting:NO]; 
} 

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { 
    [fireView setIsEmitting:NO]; 
} 
-(void)setIsEmitting:(BOOL)isEmitting 
{ 
    //turn on/off the emitting of particles 
    [fireEmitter setValue:[NSNumber numberWithInt:isEmitting?200:0] forKeyPath:@"emitterCells.fire.birthRate"]; 
} 
0

archivo .h

#import <UIKit/UIKit.h> 

    @interface DWFParticleView : UIView 

    -(void)setEmitterPositionFromTouch: (CGPoint*)t; 
    -(void)setIsEmitting:(BOOL)isEmitting; 

    @end 

archivo .m

#import "DWFParticleView.h" 
    #import <QuartzCore/QuartzCore.h> 

    @implementation DWFParticleView 
    { 
     CAEmitterLayer* fireEmitter; //1 
    } 

    -(void)awakeFromNib 
    { 
     //set ref to the layer 
     fireEmitter = (CAEmitterLayer*)self.layer; //2 
     //configure the emitter layer 
     fireEmitter.emitterPosition = CGPointMake(50, 50); 
     fireEmitter.emitterSize = CGSizeMake(10, 10); 

     CAEmitterCell* fire = [CAEmitterCell emitterCell]; 
     fire.birthRate = 0; 
     fire.lifetime = 1.5; 
     fire.lifetimeRange = 0.3; 
     fire.color = [[UIColor colorWithRed:255 green:255 blue:255 alpha:0.1] CGColor]; 
     fire.contents = (id)[[UIImage imageNamed:@"Particles_fire.png"] CGImage]; 
     [fire setName:@"fire"]; 

     fire.velocity =5; 
     fire.velocityRange = 20; 
     fire.emissionRange = M_PI_2; 

     fire.scaleSpeed = 0.1; 
     fire.spin = 0.5; 

     fireEmitter.renderMode = kCAEmitterLayerAdditive; 

     //add the cell to the layer and we're done 
     fireEmitter.emitterCells = [NSArray arrayWithObject:fire]; 

    } 

    + (Class) layerClass //3 
    { 
     //configure the UIView to have emitter layer 
     return [CAEmitterLayer class]; 
    } 

    -(void)setEmitterPositionFromTouch: (CGPoint*)t 
    { 
     //change the emitter's position 
     fireEmitter.emitterPosition = (*t); 
    } 

    -(void)setIsEmitting:(BOOL)isEmitting 
    { 
     //turn on/off the emitting of particles 
     [fireEmitter setValue:[NSNumber numberWithInt:isEmitting?100:0] forKeyPath:@"emitterCells.fire.birthRate"]; 
    } 


    @end 

He utilizado este código para crear una vista personalizada y para emitir parti culos en contacto

Aquí está la instrucción de llamada para la emisión de partículas en contacto

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    CGPoint p = [[touches anyObject] locationInView:self.view]; 
    [fireView setEmitterPositionFromTouch: &p]; 
    [fireView setIsEmitting:YES]; 

} 

puede ser que funcione para usted.

4

Sé que esta es una publicación anterior, pero también tuve este problema. Jackslash responde bien en este post: iOS 7 CAEmitterLayer spawning particles inappropriately

Es necesario configurar beginTime en su capa emisora ​​para comenzar en el momento actual con CACurrentMediaTime(). Parece que el problema que tenemos se debe a que el emisor ya comenzó en el pasado.

emitter.beginTime = CACurrentMediaTime(); 
Cuestiones relacionadas