CAEmitterLayer 连续发射一行

CAEmitterLayer emit continuously in a line

我正在使用 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];

现在,我将 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跟着你的touch up,像绘图一样连续发射这些粒子而不被点缀?

谢谢

我建议删除动画并通过 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];

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

把动画的定时功能改成线性的,应该就能看到你想要的效果了。

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

您还需要稍微调整一下比例,并可能使用 CAShapeLayer 绘制您想要的实际线条。

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

我觉得您的 birthRate 设置得太低了。尝试将其从 250.f 更改为 1500.f 和 post 之类的结果。

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

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

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