2012-07-11 10 views
39

Sto cercando di creare un CAEmitterLayer a fare un effetto coriandoli, e ho incontrato due problemi:CAEmitterLayer emette particelle indesiderate casuali su eventi touch

  1. Ogni volta che ho impostato il birthRate sulle mie cellule a qualcosa di diverso da zero per avviare l'animazione ottengo una raffica di celle posizionate casualmente sullo schermo, che animano normalmente, e poi l'emettitore continua ad emettere correttamente dopo di ciò.
  2. Ogni volta che lo emitterCells disegna sullo schermo, ogni volta che tocco lo schermo, l'emettitore disegna emitterCells in posizioni (apparentemente) casuali che esistono per una quantità (apparentemente) casuale di tempo. Nulla nell'emettitore è legato ad alcun evento di tocco (ad esempio, non sto disegnando intenzionalmente nulla su un evento touch), ma il livello è in una vista che ha più viste incorporate. Più tocco, più cellule appaiono.

Ecco il mio codice per impostare l'emettitore, e poi avvio e l'arresto di esso (una volta ho chiamato la funzione di arresto, poi rubinetti sullo schermo cessate creazione di nuovi elementi casuali):

- (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]; 
} 

per avviare il confetti:

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

E per fermarlo:

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

Ancora una volta, una volta iniziato, dopo il turbinio iniziale di elementi casuali, funziona perfettamente: tutto si anima normalmente e quando il valore di nascita viene successivamente azzerato, termina con grazia. Sembra solo rispondere agli eventi touch, e non ho idea del perché. Ho provato ad aggiungere emitterLayer a una vista diversa, disabilitare l'interazione dell'utente su quella vista e aggiungerla come sottoview della vista principale, e non sembrava funzionare.

Qualsiasi aiuto/approfondimento sarebbe molto apprezzato!

Grazie, Sam

+4

Hai scoperto qualcosa a riguardo? Sto avendo lo stesso problema anche io. Sembra una "caratteristica" molto inutile per me. –

+4

Forse dopo un anno dall'ultimo commento in questo post qualcuno ha trovato la soluzione a questo problema? Vedo questo problema in ogni progetto fondato nel web che utilizza la classe CAEmitterLayer. Puoi provare anche con questo tutorial: http://www.raywenderlich.com/6063/uikit-particle-systems-in-ios-5-tutorial. Basta rimuovere la gestione dei touch da vc e ridurre birthRate a 1 per esempio, e iniziare a registrare ovunque. Tutte le particelle vere sembrano essere raddoppiate dopo aver toccato. Il problema appare solo sui dispositivi, non nel simulatore. –

risposta

1

Potrebbe essere che non si sta verificando, per vedere se la particella emette come nell'esempio Wenderlich Artur Ozieranski postato? Non vedo il raddoppio finché il controllo è a posto.

- (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

file h

#import <UIKit/UIKit.h> 

    @interface DWFParticleView : UIView 

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

    @end 

di file .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 

Ho usato questo codice per creare una visualizzazione personalizzata e di emettere parti Cles su tocco

Ecco la dichiarazione richiesta di emissione di particelle sul touch

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

} 

può essere che lavorerà per voi.

4

So che questo è un vecchio post, ma ho anche avuto questo problema. Jackslash risponde bene in questo post: iOS 7 CAEmitterLayer spawning particles inappropriately

È necessario impostare BEGINTime sul vostro strato emettitore per iniziare al tempo corrente con CACurrentMediaTime(). Sembra che il problema si sia verificato perché l'emettitore è già stato avviato in passato.

emitter.beginTime = CACurrentMediaTime(); 
Problemi correlati