【问题标题】:CAEmitterLayer emit continuously in a lineCAEmitterLayer 连续发射一行
【发布时间】:2015-02-07 18:17:16
【问题描述】:

我正在使用 CoreAnimation 创建一个非常简单的粒子系统。

这是我的牢房:

UIImage *image = [UIImage imageNamed:@"spark"];
CAEmitterCell *cell = [CAEmitterCell emitterCell];
[cell setContents:(id)image.CGImage];
[cell setBirthRate:250.f];
[cell setScale:.25f];
[cell setColor:[UIColor colorWithRed:1.0 green:0.2 blue:0.1 alpha:0.5].CGColor];
[cell setLifetime:5.0f];

和层:

CAEmitterLayer *emitterLayer = [CAEmitterLayer layer];
[emitterLayer setEmitterCells:@[cell]];
[emitterLayer setFrame:bounds];
[emitterLayer setRenderMode:kCAEmitterLayerAdditive];
[self.view.layer addSublayer:emitterLayer];

现在,我将发射器层的位置移动到我要触摸的任何位置:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    self.emitterLayer.emitterPosition = [[touches anyObject] locationInView:self.view];
}

但是,问题是,它不会连续发射粒子。而是每隔一定的时间(点与线相反):

我想也许是因为我没有为它制作动画。所以我尝试添加一个简单的动画来将发射器从屏幕的左上角移动到右下角,看看是否可行:

CGPoint startPos = CGPointZero;
CGPoint endPos = CGPointMake(bounds.size.width, bounds.size.height);

CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"emitterPosition"];
ba.fromValue = [NSValue valueWithCGPoint:startPos];
ba.toValue = [NSValue valueWithCGPoint:endPos];
ba.duration = .5f;
[emitterLayer addAnimation:ba forKey:nil];

我预计会形成一条由连续发射的粒子形成的线。但是,我看到的粒子是间隔发射的,像这样:

是否可以让emitterLayer 跟随您的修饰并像绘图一样连续发射这些粒子而不是点缀?

谢谢

【问题讨论】:

    标签: ios objective-c iphone core-animation particle-system


    【解决方案1】:

    您希望达到的效果(我在评论中看到了一个链接)可能最好在没有粒子系统的情况下实现。您通常使用什么来实现这种效果取决于个人方法,但我在这两种方法上都取得了成功。

    一个,是创建一个渲染缓冲区:你直接在这个缓冲区上绘制一个最大值的颜色。例如,这可能是UIView。每隔一段时间,您会将该视图中的每个像素值减少一个百分比(例如 0.05%)。以这种方式添加的新像素随着时间的推移开始变亮并逐渐消失,因此点之间没有间隙。这是 CPU 密集型的!

    另一种方法是创建“三角形”:您需要为此使用较低级别的图形 API,例如 OpenGL。这个想法是你创建一个三角形(或四边形)的一部分,在你的手指下形成一个“丝带”。添加的每个新部分都开始褪色到 0% alpha,然后被删除。在 cocos2d 中有一个这种技术的实现,称为CCMotionStreak,非常适合这个。好处是你提供了一个纹理(就像你提供一个粒子系统一样),所以它让设计师满意

    【讨论】:

      【解决方案2】:

      我建议删除动画并通过CAEmitterCellvelocityemissionLongitude 属性创建线条效果:

      UIImage *image = [UIImage imageNamed:@"spark"];
      CAEmitterCell *cell = [CAEmitterCell emitterCell];
      [cell setContents:(id)image.CGImage];
      [cell setBirthRate:250.f];
      [cell setScale:.25f];
      [cell setColor:[UIColor colorWithRed:1.0 green:0.2 blue:0.1 alpha:0.5].CGColor];
      [cell setLifetime:5.0f];
      [cell setEmissionLongitude:M_PI_4]; //The emission angle
      [cell setVelocity:500]; //adjust as needed, together with BirthRate
      
      
      CAEmitterLayer *emitterLayer = [CAEmitterLayer layer];
      [emitterLayer setEmitterCells:@[cell]];
      [emitterLayer setFrame:bounds];
      [emitterLayer setRenderMode:kCAEmitterLayerAdditive];
      [self.view.layer addSublayer:emitterLayer];
      

      【讨论】:

        【解决方案3】:

        这看起来非常像您使用缓入缓出动画曲线看到的模式,我认为这是 CAAnimations 的默认设置。两端的点更靠近,表明开始和结束时速度较慢。

        将动画的计时功能改为线性,你应该会看到你想要的效果。

        要获得连续的发射器线,我唯一能做的就是减慢动画速度,这并不能真正产生正确的效果。看起来移动发射器位置会跳过一些渲染,我不知道为什么。

        您还需要稍微调整一下缩放比例,并且可能使用 CAShapeLayer 来绘制您所追求的实际线条。

        事实上,一个更好的解决方案可能是使用一个较小的发射器层,您可以在该行的末端移动它,并使用一个 CAShapeLayer,您可以为 strokeEnd 设置动画以将绘图保留在那里。

        【讨论】:

        • 试过了,但这并不能解决问题。还是有差距的。我正在寻找一种方法来做到这一点,所以没有差距。一条连续的线。
        • 像火一样沿着保险丝移动吗?
        • 啊!在那种情况下,我误解了你的问题。让我看看然后回复你
        • 酷,谢谢!如果有帮助,这里有一段视频,显示了我的意思:youtube.com/watch?v=shirth1OjRE#t=167(2:45)。
        【解决方案4】:

        在我看来,您的birthRate 设置得太低了。尝试将其从 250.f 更改为 1500.f 并发布结果。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-04
          • 2021-05-23
          • 1970-01-01
          相关资源
          最近更新 更多