【Flutter&Flame游戏 - 拾伍】粒子系统 | ParticleSystemComponent

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 16 天,点击查看活动详情


前言

这是一套 张风捷特烈 出品的 Flutter&Flame 系列教程,发布于掘金社区。如果你在其他平台看到本文,可以根据对于链接移步到掘金中查看。因为文章可能会更新、修正,一切以掘金文章版本为准。本系列源码于 【toly_game】 ,如果本系列对你有所帮助,希望点赞支持,本系列文章一览:


1. Flame 中的粒子系统

Flame 中,一切的呈现都依赖于构件,粒子系统也不例外。目前和粒子相关的有两个构件,其中 ParticleComponent 已经过时了,不推荐使用。所以 Flame 中的粒子系统主要使用的是 ParticleSystemComponent 构件。


首先说一下什么是粒子,举个观的例子:现实中烟花的爆炸,会生成大量细小的颗粒,维持短暂的时间后消失。像这样的大量的,有存在时间的显示物就可以通过粒子系统来呈现。Flame 的官方案例中有一些案例,但放在一块有些杂乱,这里将用 2 篇文章,由详细介绍一下 ParticleSystemComponent 的使用。

image-20220607121048917.png


2. 通过 ParticleSystemComponent 显示一个粒子

如下,使用 ParticleSystemComponent 构件,显示一个生命时长为 1 s 的圆形粒子:代码详见 【15/01】

使用 ParticleSystemComponent 有三个步骤:

  • 1. 创建 Particle 粒子对象
  • 2. 创建 ParticleSystemComponent 构件对象
  • 3. 将构建加入到树中,进行显示

其中 2、3 步骤非常简单,所以对于粒子系统而言,如何创建 Particle 对象是重中之重。这里显示一个圆形的粒子,可以使用 Particle 的衍生类 CircleParticle 。其中有三个入参:paint 表示粒子的绘制画板;radius 表示粒子的半径;lifespan 表示粒子的存在多少秒后消失。

void createParticle(){
  // 创建 Particle 对象
  Paint circlePaint = Paint()..color = Colors.white;
  Particle particle = CircleParticle(
    paint: circlePaint,
    radius: 20,
    lifespan: 1,
  );
  // 创建 ParticleSystemComponent 构件
  final ParticleSystemComponent psc = ParticleSystemComponent(
    particle: particle,
  );
  // 添加 ParticleSystemComponent 构件
  add(psc);
}
复制代码

3. 区分 ParticleSystemComponent 和 Particle

在进一步介绍粒子系统之前,有必要先认识一下 ParticleSystemComponentParticle 两个类之间的区别与联系。从如下 ParticleSystemComponent 源码中可以看出,它是一个 PositionComponent ,构造时必须传入 Particle 对象。另外构造时还可以指定一些 PositionComponent 的大小、位置、锚点等属性。


Particle 本身只是抽象类,不是 Component 的衍生类,它有自己的衍生体系。

如下,在 Flameparticles 包中定义了很多实现类以供使用:


瞄一下 CircleParticle 的源码可以看出,其实现还是非常简单的,就是画个圈而已。如果有需要的话,我们也可以根据需求来自己定义 Particle 。核心就是在 render 方法了进行绘制,有了 Canvas ,就可画万物。


4. 移动粒子 MovingParticle

Particle 的衍生类中可以看到有很多支持传入 child 的例子,这些实现类往往可以基于某个粒子,是些特点的功能。比如 MovingParticle 可以让粒子进行运动,如下所示:可以让粒子在 lifespan 时间内,按照 curve 的变化曲线,从起点移动到终点。 【15/02】

// 创建 Particle 对象
Paint circlePaint = Paint()..color = Colors.white;
Particle particle = MovingParticle(
  lifespan: 3,
  curve: Curves.easeIn,
  from: Vector2.zero(),
  to: Vector2(200,0),
  child: CircleParticle(
    radius: 20.0,
    paint: circlePaint,
  ),
);
复制代码

5.批量生成粒子

Particle 有个 generate 的方法可以生成多个粒子,下面是 Flame 官方的一个小例子,感觉挺有趣,这里来看一下。代码详见 【15/03】

这里通过 Particle.generate 生成多个粒子,其中 count 表示粒子生成粒子的数量,generator 是根据索引生成 Particle 的函数;再使用 MovingParticle 实现粒子的移动;另外使用 PaintParticle 通过调节 paintblendMode ,产生叠合效果。

其实这里不用 PaintParticle ,直接设置 CircleParticle#paintblendMode 也可以得到相同的效果。可能是案例想多介绍一种 Particle 吧。

final List<Color> colors = [
  const Color(0xffff0000),
  const Color(0xff00ff00),
  const Color(0xff0000ff),
];

final List<Vector2> positions = [
  Vector2(-10, 10),
  Vector2(10, 10),
  Vector2(0, -14),
];

// 创建 Particle 对象
Particle particle = Particle.generate(
  count: 3,
  lifespan: 3,
  generator: (i) => PaintParticle(
    paint: Paint()..blendMode = BlendMode.difference,
    child:MovingParticle(
    curve: Curves.easeIn,
    from: positions[i],
    to: i == 0 ? positions.last : positions[i - 1],
    child: CircleParticle(
      radius: 20.0,
      paint: Paint()..color = colors[i],
    ),
  ),
));
复制代码

本问简单介绍了一下 ParticleSystemComponent 的使用,并了解了 CircleParticleMovingParticlePaintParticleParticle.generate 的使用。下一篇我们将进一步认识 Particle 一族,并结合随机数来完成某些粒子效果。那本文就到这里,明天见 ~

\

猜你喜欢

转载自juejin.im/post/7107404963781246990