前情提要来自作者上一步的代码雨
此文章是上一篇的dlc,新添加爆炸粒子效果

实现原理是在消散时加上粒子爆炸的效果
怎么实现粒子爆炸的效果
和雨滴一样,粒子也要有一个类来存储状态
dart
// 粒子 爆炸后的
class Particle {
Offset position;
Offset velocity;
double alpha = 1.0;
int lifespan;
int age = 0;
Particle({
required this.position,
required this.velocity,
required this.lifespan,
});
void update() {
position += velocity;
age++;
alpha = (1.0 - age / lifespan).clamp(0.0, 1.0);
}
bool get isDead => age >= lifespan;
}
来分析一下属性
- position 位置
- velocity 速度
- alpha 角度
- lifespan 生命周期
- age 当前生命
update
方法用来实时更新爆炸粒子的状态,以及随机角度alpha = (1.0 - age / lifespan).clamp(0.0, 1.0);
bool get isDead => age >= lifespan;
当当前生命age
大于生命周期lifespan
时,粒子死亡isDead
至此,一个粒子的类就创建好了
接下来是在哪去使用这个粒子,粒子牵扯到雨滴的位置,所以粒子不用去单独创建一个manage管理类,而是和雨滴共用一个管理类去实现 在原先的RainManager
中添加final List<Particle> particles = [];
以及新的方法
explodeAt()
粒子爆炸
dart
void explodeAt(double x, double y) {
for (int i = 0; i < 10; i++) {
final angle = random.nextDouble() * 2 * pi;
final speed = 1 + random.nextDouble() * 2;
final velocity = Offset(cos(angle), sin(angle)) * speed;
particles.add(
Particle(
position: Offset(x, y),
velocity: velocity,
lifespan: 60,
),
);
}
}
那么粒子该什么时候出现,怎么去更新状态呢 当然还是依靠雨滴,只有当雨滴超出屏幕消失时出发消散才会有粒子爆炸(==当然也增加更多的触发条件,但本质上还是和雨滴依依相靠==) 所以爆炸粒子的生成放在了雨滴的更新里
dart
void update() {
for (final drop in drops) {
drop.y += drop.speed;
drop.frameCount++;
// 超出屏幕时触发爆散
if (drop.y > size.height) {
explodeAt(drop.x, drop.y);
drop.x = random.nextDouble() * size.width;
drop.y = 0;
drop.speed = 1 + random.nextDouble() * 2;
drop.frameCount = drop.frameOffset;
}
}
// 更新粒子
for (final particle in particles) {
particle.update();
}
//移除死亡的粒子
particles.removeWhere((p) => p.isDead);
}
那粒子的绘制也是放在雨滴的绘制里
dart
void paint(Canvas canvas, Size size) {
// 绘制雨滴
for (final drop in manager.drops) {
...
}
// 绘制粒子
for (final particle in manager.particles) {
paint.color = Colors.green.withOpacity(particle.alpha);
canvas.drawCircle(particle.position, 1.5, paint);
}
...
}