带排斥对象的粒子系统
2024-05-22 00:00:02  阅读数 708

书名:代码本色:用编程模拟自然系统
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
目录

4.12 带排斥对象的粒子系统

1、带排斥对象的粒子系统

  我们想进一步优化这个粒子系统,在其中加入一个排斥对象(Repeller)——排斥对象的作用力和第2章中的引力相反,排斥对象对其他对象有斥力作用,以防止对方靠近。这个特性实现起来比较复杂,和重力不同,Attractor或者Repeller对每个粒子的作用力都不相同,我们需要逐个计算。


我们打算在上面的示例程序中加入这个排斥对象。我们需要加入两个额外的功能点:

  • 1.排斥对象(声明、初始化和显示);
  • 2.在粒子系统中加入一个新函数,该函数以Repeller对象为参数,它的功能是将排斥力作用在每个粒子上。

请注意一个关键点,在加入排斥对象的整个过程中,我们从来没有直接在Particle类上作任何修改。粒子不需要知道外部环境的细节,它只需要管理自身的位置、速度和加速度,并接受外力作用。

2、示例

示例代码4-7 带Repeller的粒子系统

ParticleSystem ps;
Repeller repeller;

void setup() {
  size(640,360);
  ps = new ParticleSystem(new PVector(width/2,50));
  repeller = new Repeller(width/2-20,height/2);
}

void draw() {
  background(255);
  ps.addParticle();
  
  // Apply gravity force to all Particles
  PVector gravity = new PVector(0,0.1);
  ps.applyForce(gravity);
  
  ps.applyRepeller(repeller);
  
  repeller.display();
  ps.run();
}

ParticleSystem.pde (同上,略)
Particle.pde (同上,略)
Repeller.pde

class Repeller {
  
  // Gravitational Constant
  float G = 100;
  // position
  PVector position;
  float r = 10;

  Repeller(float x, float y)  {
    position = new PVector(x,y);
  }

  void display() {
    stroke(0);
    strokeWeight(2);
    fill(175,0,0);
    ellipse(position.x,position.y,48,48);
  }

  // Calculate a force to push particle away from repeller
  PVector repel(Particle p) {
    PVector dir = PVector.sub(position,p.position);      // Calculate direction of force
    float d = dir.mag();                       // Distance between objects
    dir.normalize();                           // Normalize vector (distance doesn't matter here, we just want this vector for direction)
    d = constrain(d,5,100);                    // Keep distance within a reasonable range
    float force = -1 * G / (d * d);            // Repelling force is inversely proportional to distance
    dir.mult(force);                           // Get force vector --> magnitude * direction
    return dir;
  }  
}

3、运行结果