书名:代码本色:用编程模拟自然系统
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
目录
4.11 受力作用的粒子系统
1、受力作用的粒子系统
以上粒子类(Particle)中的加速度是一个常量,它从来不会发生变化。然而,一个更好的模拟框架应该遵循牛顿第二定律(F = M * A),并能将第2章中力的累加算法作用在粒子上,下面就让我实现这样的特性。
第一步,我们需要添加一个applyForce()函数。(记住:在将力向量除以质量之前,我们要先创建一个副本。)
我们还要在update()函数中多加一行代码,用于清除之前的加速度。完成Particle类之后,我们还有一个很重要的问题:
在何处调用applyForce()函数,即在代码的哪个位置实现力对粒子的作用?
事实上,这个问题没有绝对正确的答案,它取决于你的具体需求。话虽如此,但我们还是可以实现一种适用于大部分情况的通用解决方案,并构造一个模型应用于每个粒子都受力的作用的系统。现在我们碰到了一个小问题,applyForce()是粒子类的方法,但是我们没法在draw()函数中引用任何粒子对象,这里只有一个粒子系统对象:变量ps。
由于系统内的所有粒子都受力的作用,所以我们可以把力作用在粒子系统上,粒子系统再将这个力传递给每个粒子。
void draw() {
background(100);
PVector gravity = new PVector(0, 0.1);
ps.applyForce(gravity); 把力作用在粒子系统上
ps.addParticle();
ps.run();
}
- 如果要在draw()函数中调用粒子系统的新函数,我们必须在粒子系统类中定义这个函数。该函数的作用是:传入力向量,将力作用在每个粒子上。
代码如下:
void applyForce(PVector f) {
for (Particle p: particles) {
p.applyForce(f);
}
}
这个函数实现起来非常简单,它的功能只是“将力作用在粒子系统上,系统再将力作用在每个粒子上”。这是一种非常合理的程序结构。因为粒子系统对象的职责是管理粒子,如果要操纵粒子,我们必须通过粒子的管理者——粒子系统。(还有,这里可以使用改进型for循环,因为我们不会在遍历过程中删除任何元素!)
2、示例
示例代码 4-6 受力作用的粒子系统
ParticleSystem ps;
void setup() {
size(640,360);
ps = new ParticleSystem(new PVector(width/2,50));
}
void draw() {
background(255);
// Apply gravity force to all Particles
PVector gravity = new PVector(0,0.1);
ps.applyForce(gravity);
ps.addParticle();
ps.run();
}
ParticleSystem.pde
class ParticleSystem {
ArrayList<Particle> particles;
PVector origin;
ParticleSystem(PVector position) {
origin = position.get();
particles = new ArrayList<Particle>();
}
void addParticle() {
particles.add(new Particle(origin));
}
// A function to apply a force to all Particles
void applyForce(PVector f) {
for (Particle p: particles) {
p.applyForce(f);
}
}
void run() {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.run();
if (p.isDead()) {
particles.remove(i);
}
}
}
}