2012-07-11 12 views
39

Ich versuche, ein CAEmitterLayer einzurichten, um einen Konfetti-Effekt zu machen, und ich habe in zwei Probleme laufen:CAEmitterLayer emittiert zufälligen unerwünschten Partikel auf Berührungsereignisse

  1. Jedes Mal, wenn ich die birthRate auf meinen Zellen auf etwas Nicht-Null, um die Animation zu starten Ich bekomme eine Vielzahl von Zellen zufällig auf dem Bildschirm platziert, die normalerweise animieren, und dann der Emitter weiterhin richtig danach emittiert.
  2. Immer, wenn die emitterCells Dinge auf dem Bildschirm zeichnen, jedes Mal, wenn ich den Bildschirm berühre, zeichnet der Emitter emitterCells in (scheinbar) zufällige Orte, die für eine (scheinbar) zufällige Zeit existieren. Nichts im Emitter ist an Berührungsereignisse gebunden (d. H. Ich zeichne absichtlich nichts auf einem Berührungsereignis), aber die Ebene befindet sich in einer Ansicht mit mehreren eingebetteten Ansichten. Je mehr ich mich berühre, desto mehr Zellen tauchen auf.

Hier ist mein Code für den Sender einrichten, und dann das Starten und Stoppen es (wenn ich die Stopp-Funktion aufgerufen haben, tippt dann auf dem Bildschirm aufhören Schaffung neuer Zufallselemente):

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

um das Konfetti zu starten:

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

Und um es zu stoppen:

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

Noch einmal, nach dem anfänglichen Aufeinanderprallen von zufälligen Elementen, funktioniert das ganz gut: alles wird normal animiert, und wenn die burthRate später auf Null gesetzt wird, endet sie anmutig. Es scheint nur auf Berührungsereignisse zu reagieren, und ich habe keine Ahnung warum. Ich habe versucht, die emitterLayer zu einer anderen Ansicht hinzuzufügen, die Benutzerinteraktion für diese Ansicht zu deaktivieren und sie dann als Unteransicht der Hauptansicht hinzuzufügen, und das schien nicht zu funktionieren.

Jede Hilfe/Einblick würde sehr geschätzt werden!

Danke, Sam

+4

Haben Sie etwas dazu herausgefunden? Ich habe das gleiche Problem. Scheint wie ein sehr unnötiges "Feature" für mich. –

+4

Vielleicht nach einem Jahr seit dem letzten Kommentar in diesem Post jemand die Lösung dieses Problems gefunden hat? Ich sehe dieses Problem in jedem Projekt im Web, das die CAEmitterLayer-Klasse verwendet. Sie können sogar mit diesem Tutorial versuchen: http://www.raywenderlich.com/6063/uikit-particle-systems-in-ios-5-tutorial. Entfernen Sie einfach Berührungen von vc und reduzieren Sie den Wert von birthRate auf 1 und beginnen Sie mit dem Tapen. Alle lebenden Partikel scheinen nach dem Tippen verdoppelt zu sein. Das Problem tritt nur auf Geräten auf, nicht im Simulator. –

Antwort

1

Könnte es sein, dass Sie nicht, wenn die Partikel zu sehen sind, überprüft wird, wie im Beispiel Wenderlich emittierenden Artur Ozieranski geschrieben? Ich sehe die Verdoppelung nicht, solange der Scheck vorhanden ist.

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

.h-Datei

#import <UIKit/UIKit.h> 

    @interface DWFParticleView : UIView 

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

    @end 

.m-Datei

#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 

ich diesen Code verwendet für eine Ansicht benutzerdefinierte erstellen und parti emittieren cles auf Touch ist

Hier der Aufruf-Anweisung für die Emission von Teilchen auf Touch

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

} 

sein kann, es wird für Sie arbeiten.

4

Ich weiß, das ist ein alter Beitrag, aber ich hatte auch dieses Problem. Jackslash beantwortet sie auch in diesem Beitrag: iOS 7 CAEmitterLayer spawning particles inappropriately

Sie benötigen Begintime auf dem Emitterschicht eingestellt werden, bei der aktuellen Zeit mit CACurrentMediaTime() zu beginnen. Es scheint, dass das Problem auftritt, weil der Emitter bereits in der Vergangenheit begonnen hat.

emitter.beginTime = CACurrentMediaTime();