用代码描述自然系统-简单粒子系统02
在前两年 H5 开始流行的时候,网上出现了许多看起来很炫酷的粒子动画效果,其中就包含了很多简单的粒子系统,本篇将基于前几篇文章的基础,实现这些看起来炫酷的效果。
构造粒子类
所有的粒子系统都必须基于一个基本的粒子类来实现,借助向量实现对粒子的物理模拟。在前面的几篇文章中,我们构建最多的就是 Mover 类,本篇我们将实现一个 Particle 类。
Particle 类与之前的 Mover 类功能大体类似,下面直接实现 Particle 类。
class Particle {
constructor(mass) {
this.mass = mass;
this.diameter = this.mass * 1;
this.position = createVector(random(PWidth), random(PHeight));
this.velocity = createVector(random(-0.5, 0.5), random(-0.5, 0.5));
this.color = color(random(100, 200), 100);
}
setColor(color) {
this.color = color;
}
setPosition(position) {
this.position = position;
}
setVelocity(vel) {
this.velocity = vel;
}
addFore(f) {
this.velocity.add(f);
}
update() {
this.position.add(this.velocity);
const r = this.diameter / 2;
if (this.position.x - r <= 0) {
this.position.x = r;
this.velocity.x *= -1;
}
if (this.position.x + r >= PWidth) {
this.position.x = PWidth - r;
this.velocity.x *= -1;
}
if (this.position.y - r <= 0) {
this.position.y = r;
this.velocity.y *= -1;
}
if (this.position.y + r >= PHeight) {
this.position.y = PHeight - r;
this.velocity.y *= -1;
}
}
display() {
fill(this.color);
noStroke();
ellipse(this.position.x, this.position.y, this.diameter);
}
}
定义规则-1
构建粒子系统另一个重要因素就是规则定义,我们即将要实现的粒子系统需要满足下面的规则:
- 粒子之间的距离大于 100 时不做处理;
- 粒子之间的距离小于 100 时,在满足距离条件的例子之间连线;
- 粒子之间的连线透明度随距离的减小而减小,即距离越大透明度越高,距离越小透明度越小;
基于以上的规则,实现 draw 函数如下:
function draw() {
background(10);
particles.forEach(particle => {
particles.forEach(op => {
if (particle === op) return;
const dist = p5.Vector.dist(particle.position, op.position);
if (dist > radius) return;
stroke(200, (1 - dist / radius) * 100);
strokeWeight(1);
line(particle.position.x, particle.position.y, op.position.x, op.position.y);
});
particle.update();
particle.display();
});
}
最终效果如下图:
真实的效果是动态的,如需在 PC 上查看效果可以 点击这里。
定义规则-2
另一种效果跟上面的类似,不过看起来更炫酷一点,就是在例子之间除了连线,还为这些连线填充颜色,这种规则可以定义如下:
- 粒子之间的距离大于 100 时不做处理;
- 粒子之间的距离小于 100 时,寻找满足距离条件的三个例子构成三角形,并为三角形填充颜色;
基于上面的规则,重新实现 darw 函数:
function draw() {
background(255);
particles.forEach(particle => {
const shapes = [];
particles.forEach(op => {
if (particle === op) return;
const dist = p5.Vector.dist(particle.position, op.position);
if (dist > radius) return;
shapes.push(op);
});
if (shapes.length > 1) {
for (let i = 0; i < shapes.length - 1; i++) {
const pointA = shapes[i], pointB = shapes[i + 1];
const fillColor = color(255, 0, 16, 10);
fill(fillColor);
triangle(particle.position.x, particle.position.y, pointA.position.x, pointA.position.y, pointB.position.x, pointB.position.y);
}
}
particle.update();
particle.display();
});
}
最终效果如下图:
可以 点击这里 查看动态效果。
其他规则
对于粒子系统而言,规则决定了粒子的表现,上面的两个示例只是简单复原了前两年比较流行的炫酷效果,但真正理解了粒子系统以后,就会发现这种规则是多么的简单。对于类似的例子系统,我们甚至可以增加鼠标交互,增加不规则受力,增加柏林噪声产生平滑扰动…
后续的文章将会有大量自然模拟,这些模拟将大量使用粒子系统。