2012-07-11 10 views
39

Próbuję założyć CAEmitterLayer aby efekt konfetti i Zabrakło mi na dwie kwestie:CAEmitterLayer emituje losowych zdarzeń niepożądanych cząstek na dotykowych

  1. Ilekroć ustawić birthRate na moich komórek do coś niezerowego, aby rozpocząć animację Dostaję falę komórek umieszczonych losowo na ekranie, które normalizują się normalnie, a następnie emiter nadal emituje prawidłowo po tym.
  2. Gdy tylko emitterCells rysuje rzeczy na ekranie, za każdym razem, gdy dotykam ekranu, emiter rysuje emitterCells w (pozornie) losowych lokalizacjach, które istnieją (na pozór) losową ilość czasu. Nic w emiterach nie jest powiązane z żadnymi zdarzeniami dotyku (tj. Nie zamierzam rysować niczego na zdarzeniu dotykowym), ale warstwa jest w widoku, który ma wiele osadzonych widoków. Im więcej się dotykam, tym więcej komórek się pojawi.

Oto mój kod do konfigurowania emiter, a następnie uruchamianie i zatrzymywanie go (raz byłem nazywany funkcja stop, potem krany na przestają ekranu tworzenia nowych elementów losowych):

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

aby rozpocząć konfetti:

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

i zatrzymać go:

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

Znowu, po uruchomieniu, po początkowym przypływie losowych elementów, działa to dobrze: wszystko ożywia się normalnie, a kiedy wartość birthRate jest później ustawiona na zero, kończy się z gracją. Wydaje się, że reaguje na zdarzenia dotykowe i nie mam pojęcia dlaczego. Próbowałem dodać emitterLayer do innego widoku, wyłączając interakcję użytkownika z tym widokiem, a następnie dodając go jako podzbiór głównego widoku, który nie działał.

Każda pomoc/wgląd byłby mile widziany!

Dzięki Sam

+4

Dowiedziałeś się czegoś na ten temat? Mam ten sam problem. Wydaje mi się to bardzo niepotrzebną "cechą". –

+4

Może po roku od ostatniego komentarza w tym poście ktoś znalazł rozwiązanie tego problemu? Widzę ten problem w każdym projekcie utworzonym w Internecie, który używa klasy CAEmitterLayer. Możesz spróbować skorzystać z tego samouczka: http://www.raywenderlich.com/6063/uikit-particle-systems-in-ios-5-tutorial. Wystarczy usunąć obsługę dotknięć z vc i zmniejszyć birthRate do 1 na przykład i zacząć nagrywać w dowolnym miejscu. Wszystkie żywe cząstki wydają się podwoić po dotknięciu. Problem pojawia się tylko na urządzeniach, a nie na symulatorze. –

Odpowiedz

1

Czy to możliwe, że nie sprawdzając, czy cząstka emituje jak w przykładzie Wenderlich Artur Ozieranski pisał? Nie widzę podwojenia tak długo, jak czek jest na miejscu.

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

plik .h

#import <UIKit/UIKit.h> 

    @interface DWFParticleView : UIView 

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

    @end 

pliku .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 

Użyłem tego kodu do utworzenia widoku niestandardowego i emitować Parti Cykle na dotyku

Oto zestawienie połączenia dla emisji cząstek na dotyk

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

} 

może być to będzie pracować dla Ciebie.

4

Wiem, że to stary post, ale też miałem ten problem. Jackslash odbiera dobrze w tym poście: iOS 7 CAEmitterLayer spawning particles inappropriately

Musisz ustawić begintime na warstwie emitera rozpocząć w chwili obecnej z CACurrentMediaTime(). Wygląda na to, że mamy problem, ponieważ emulator rozpoczął się już w przeszłości.

emitter.beginTime = CACurrentMediaTime(); 
Powiązane problemy