群体活动(不要遇到对方)

分享
开发者 2024-9-8 01:10:35 108 0 来自 中国
书名:代码本色:用编程模拟自然体系
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
第6章目次
6.11 群/体活动(不要遇到对方)

1、ArrayList


  • 在粒子体系类中,我们用ArrayList存放粒子的列表。我们会在本例中做同样的变乱:把一组Vehicle对象存放到ArrayList中。
ArrayList<Vehicle> vehicles;   声明由小车对象构成的ArrayListvoid setup() {    vehicles = new ArrayList<Vehicle>; 用一系列小车对象添补ArrayList    for (int i = 0; i < 100; i++) {        vehicles.add(new Vehicle(random(width),random(height)));    }}2、draw()函数


  • 假如要在draw()函数中处理处罚全部小车对象,只需遍历这个ArrayList,并在对象上调用相应的方法。
void draw(){      for (Vehicle v : vehicles) {          v.update();          v.display();      }}3、添加活动


  • 我们要为小车添加一种活动。比如让小车探求鼠标地点的目标位置:
v.seek(mouseX, mouseY);

  • 但这只是个体的活动,前面我们一直在研究个体的活动,现在要研究群体活动。让我们从分离(separate)活动开始。分离活动等同于以下下令:“请不要和你的邻人发生碰撞!”
v.separate();

  • 这个函数另有些题目,我们还少了一些东西。分离指的是“从其他个体上分开”,其他个体指的是列表中的其他小车。
v.separate(vehicles);4、群体活动的实现


  • 相比于粒子体系,本例有很大差别。在粒子体系中,个体(粒子或小车)单独运作;
    但在本例中,我们会告诉个体:“现在轮到你操纵了,你必要思量体系中的每个个体,所以我要向你传入一个ArrayList,内里存放了全部其他个体。”
  • 为了实现群体活动,我们用以下代码实现setup()函数和draw()函数。
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、转向力


  • 这只是一个开头,真正的操纵在separate()函数中实现。我们先思考这个函数的实现方式。Reynolds提到:“用转向克制拥堵”,也就是说,假如某辆小车和你的间隔太近,你应该转向以阔别它。对此你是否以为很熟悉?“探求活动”指的是朝着目标转向,将“探求活动”的转向力反转,就能得到躲避活动的转向力。


  • 但假犹如时有多辆小车的间隔都很近,这时间该怎么做?在这种情况下,我们可以对全部阔别小车的向量求匀称值,用匀称向量盘算分离活动的转向力。

    2.png
6、separate()函数的实现


  • 下面我们开始实现separate()函数,它的参数是一个ArrayList对象,内里存放了全部小车对象。
  • 在这个函数中,我们要遍历全部的小车,查抄它们是否过于靠近。
    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();}

  • 有了这个diff向量还不敷,我们还要针对每辆靠近的小车盘算diff向量,再盘算它们的匀称向量。将全部向量加在一起,再除以总数,就可以得到匀称向量!
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);}

  • 有了匀称向量(sum向量)之后,我们将它延伸至最大速率,就可以得到所需速率——盼望小车以最大速率朝着这个方向活动!一旦有了所需速率,我们就可以根据Reynolds的公式盘算转向力:
    转向力 = 所需速率 - 当前速率。
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、运行效果

您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2025-2-1 20:58, Processed in 0.201647 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表