受力作用的粒子系统
2024-04-09 21:00:19  阅读数 867

书名:代码本色:用编程模拟自然系统
作者: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);
      }
    }
  }
}

3、运行结果