群体行为(不要碰到对方)

2022-07-10  本文已影响0人  大龙10

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

6.11 群/体行为(不要碰到对方)

1、ArrayList

ArrayList<Vehicle> vehicles;   声明由小车对象组成的ArrayList
void setup() {
    vehicles = new ArrayList<Vehicle>; 用一系列小车对象填充ArrayList
    for (int i = 0; i < 100; i++) {
        vehicles.add(new Vehicle(random(width),random(height)));
    }
}

2、draw()函数

void draw(){
      for (Vehicle v : vehicles) {
          v.update();
          v.display();
      }
}

3、添加行为

v.seek(mouseX, mouseY);
v.separate();
v.separate(vehicles);

4、群体行为的实现

ArrayList&lt;Vehicle> vehicles;
void setup() {
    size(320,240);
    vehicles = new ArrayList&lt;Vehicle>();
    for (int i = 0; i < 100; i++) {
          vehicles.add(new Vehicle(random(width),random(height)));
      }
}
void draw() {
      background(255);
      for (Vehicle v : vehicles) {
          v.separate(vehicles); 这是本节加入的新东西,小车在计算分离转向力时需要检查其他所有对
          v.update();
          v.display();
      }
}

5、转向力

6、separate()函数的实现

    float desiredseparation = 20; 这个变量指定最短距离
    for (Vehicle other : vehicles) {
        float d = PVector.dist(location, other.location); 当前小车和其他小车之间的距离
        if ((d > 0) && (d < desiredseparation)) { 如果小车的距离小于20像素,这里的代码就会执行
        }
    }

注意:在上面的代码中,我们不只检查距离是否小于desiredseparation(过于接近!),还要检查距离是否大于0。这么做是为了确保小车不会意图和自身分离。所有小车对象都在ArrayList中,一不小心你就会让一辆小车与自身发生比较。

if ((d > 0) && (d < desiredseparation)) {
      PVector diff = PVector.sub(location, other.location); 一个指向远离其他小车方向的向量
      diff.normalize();
}
PVector sum = new PVector(); 从一个空向量开始
int count = 0;
for (Vehicle other : vehicles) { 我们还要记录有多少辆小车的距离过近
    float d = PVector.dist(location, other.location);
    if ((d > 0) && (d < desiredseparation)) {
        PVector diff = PVector.sub(location, other.location);
        diff.normalize();
        sum.add(diff); 将所有向量加在一起,并递增计数器
        count++;
      }
}
if (count > 0) { 必须确保至少找到一辆距离过近的小车,然后才执行除法操作(避免除零的情况!)
      sum.div(count);
}
if (count > 0) {
      sum.div(count);
      sum.setMag(maxspeed); 延伸至最大速率(使其成为所需速度)
      PVector steer = PVector.sub(sum,vel); Reynolds的转向力公式
      steer.limit(maxforce);
      applyForce(steer); 将力转化为小车的加速度
}

7、示例

示例代码6-7 群集行为:分离

void separate (ArrayList&lt;Vehicle> vehicles) {
      float desiredseparation = r*2; 分离的距离取决于小车的尺寸
      PVector sum = new PVector();
      int count = 0;
      for (Vehicle other : vehicles) {
            float d = PVector.dist(location, other.location);
            if ((d > 0) && (d < desiredseparation)) {
                  PVector diff = PVector.sub(location, other.location);
                  diff.normalize();
                  diff.div(d); 计算小车和其他小车之间的距离:距离越近,分离的幅度越大;距离越远,分离sum.add(diff);
                  count++;
              }
        }
        if (count > 0) {
            sum.div(count);
            sum.normalize();
            sum.mult(maxspeed);
            PVector steer = PVector.sub(sum, vel);
            steer.limit(maxforce);
            applyForce(steer);
        }
}

8、运行结果

上一篇 下一篇

猜你喜欢

热点阅读