38 votes

CAEmitterLayer émet des particules indésirables aléatoires lors d'événements tactiles

Je suis en train de configurer un CAEmitterLayer faire un confetti effet, et j'ai couru en deux questions:

  1. Chaque fois que j'ai défini l' birthRate sur mes cellules à quelque chose de non-zéro pour démarrer l'animation je reçois une avalanche de cellules placées au hasard sur l'écran, qui animent normalement, puis l'émetteur continue à émettre correctement par la suite.
  2. Chaque fois que l' emitterCells sont le dessin des choses sur l'écran, une fois que je touche l'écran, l'émetteur attire emitterCells dans (apparemment) des emplacements aléatoires qui existent pour un (presque) aléatoire quantité de temps. Rien dans l'émetteur est lié à un événement de touche (c'est à dire que je ne suis pas intentionnellement dessin quoi que ce soit sur un événement tactile), mais la couche est dans une vue qui a plusieurs des vues intégrées. Le plus que je touche, plus le nombre de cellules se montrer.

Voici mon code pour la configuration de l'émetteur, puis le démarrage et l'arrêt, il (une fois que j'ai appelé la fonction d'arrêt, puis appuis sur l'écran cesse de créer de nouveaux éléments aléatoires):

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

Pour lancer les confettis:

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

Et pour l'arrêter:

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

Encore une fois, une fois qu'il est démarré, après la première vague des éléments aléatoires, cela fonctionne bien: tout ce qui anime normalement, et quand le taux de natalité est ensuite remis à zéro, il se termine normalement. Il semble juste de répondre à des événements tactiles, et je n'ai aucune idée pourquoi. J'ai essayé d'ajouter le emitterLayer un autre point de vue, la désactivation de l'interaction de l'utilisateur sur ce point de vue, et puis l'ajouter comme une sous-vue de la vue principale, et qui n'a pas l'air de fonctionner.

Toute aide/insight serait bien apprécié!

Merci, Sam

1voto

DCGoD Points 2848

Se pourrait-il que vous ne vérifiiez pas si la particule émet comme dans l'exemple de Wenderlich publié par Artur Ozieranski? Je ne vois pas le double tant que le chèque est en place.

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

0voto

ROHIT Points 31

fichier .h

  #import <UIKit/UIKit.h>

    @interface DWFParticleView : UIView

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

    @end
 

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

J'ai utilisé ce code pour créer une vue personnalisée et pour émettre des particules au toucher

Voici la déclaration d'appel pour l'émission de particules au toucher

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

}
 

peut-être que cela fonctionnera pour vous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X