# Boids - Can I improve my method / efficiency?

**URL:** <https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256>\
**Category:** Coding Questions\
**Created:** [April 29, 2020, 3:17am UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256 "2020-04-29T03:17:02Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![ketchupmustard](https://avatars.discourse-cdn.com/v4/letter/k/47e85d/32.png) [@ketchupmustard](https://discourse.processing.org/u/ketchupmustard)\
**Post date:** [April 29, 2020, 3:17am UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/1 "2020-04-29T03:17:02Z")

</div>

Hi all, first post!  
So this is my first big stab at **boids**. It’s still kinda wonky - I plan to implement more features and corrections. I’m more looking for any general tips to increase efficiency (I’m not sure if it’s just my computer’s lack of a graphics card but it can be rather laggy.)  
I’d be open to any feedback on my methodology or more general tips. I’m basically just teaching myself right now so I don’t really know what I’m doing.  
Thanks!

```auto
Bird [] birds;

PVector sum, nextP, avgHead, avgLoc, avgLocDirection, avgHeadUnit;
int a, b, count, size, bIndicator;
boolean loop;
float speed, augAvgHeading, augAvgLoc, maxAug, incrAug, 
  finalDir, augSplit, avoidDir, avoidLERP, PS, check, closest;  
int target, num;
color BG;

void setup() {
  colorMode(RGB, 255, 255, 255);
  fullScreen();
  smooth();
  BG = color(240, 230, 230);
  //strokeWeight(4);
  frameRate(30);

  loop = true;
  num = 500; //num birds
  avgLoc = new PVector(0, 0);
  avgHead = new PVector(0, 0);
  avgHeadUnit = new PVector(0, 0);
  augSplit = 0.75; //for lerp: lower weights towards avgLoc, higher towards avgHeading
  maxAug = 0.1; //augmentation increment (& limit) to each bird's velocity heading, for each round of loop
  PS = 25; //personal space of each bird
  size = 2;
  avoidLERP = 0.8; //how much a bird alters its course based on proximity
  noStroke();

  birds = new Bird [num];
  for (int c = 0; c < num; c++) {
    birds[c] = new Bird();
  }
}

void draw() {
  avgHead.set(0, 0);
  avgLoc.set(0, 0);
  textSize(25);
  fill(0);
  stroke(0);
  background(BG);

  for (int c = 0; c < num; c++) //gets heading and location values from each 'bird'
  {  
    avgHead.add(birds[c].unitVector()); //vector sum of every bird's heading
  }

  if (mousePressed)
  {
    avgLoc.set(mouseX, mouseY);
  } else {     
    for (int c = 0; c < num; c++) //gets heading and location values from each 'bird'
    {  
      avgLoc.add(birds[c].loc);
    }
    avgLoc.div(num);
  }

  //avgLoc pointer
  stroke(150, 0, 0);
  ellipse(avgLoc.x, avgLoc.y, size, size);

  for (int c = 0; c < num; c++) //calculate angle-augmentation (rotation) for each bird
  {
    incrAug=maxAug; 
    fill(0);

    avgLocDirection = PVector.sub(avgLoc, birds[c].loc);
    finalDir = ( ( avgHead.heading() - avgLocDirection.heading() + 3*PI ) % TWO_PI ) - PI; //determines range between two headings
    // weighted average : LERP method    
    finalDir = lerp(0, finalDir, augSplit); 
    finalDir = ((avgLocDirection.heading() + finalDir ) % TWO_PI ) ; //determines final resting place of aspired direction
    finalDir = (( finalDir - birds[c].vel.heading() + 3*PI ) % TWO_PI ) - PI; //determines finalAug

    closest = PS; 
    bIndicator = num+1;
    for (int d = num-1; d >= 0; d--) //check and adjust for bird-bird proximity
    {
      if (c != d) {
        check = PVector.dist(birds[c].loc, birds[d].loc);
      }
      if (check < PS) {
        if (check < closest)
        {
          closest = check; 
          bIndicator = d;
        }
      }
    } 
    if (bIndicator != num+1)
    {    
      avoidDir = (((PVector.sub(birds[c].loc, birds[bIndicator].loc)).heading() - birds[c].vel.heading() + 3*PI ) % TWO_PI ) - PI; 
      finalDir = lerp(finalDir, avoidDir, avoidLERP);
    }                          

    if (incrAug >= abs(finalDir)) //smooths motion a little
    {
      birds[c].vel.rotate(finalDir);
    } else {
      incrAug = (finalDir / abs(finalDir)) * incrAug;
      birds[c].vel.rotate(incrAug);
    }
    birds[c].updateLoc();

    if (bIndicator != num+1) { 
      fill( 0, 0, lerp(0, 255, -closest/PS+1.5)); //bird turns blue when close to others
    }
    ellipse(birds[c].loc.x, birds[c].loc.y, size, size);
  }
}

//-----------//

void keyReleased() {
  noLoop();
  loop = false;
}

class Bird {

  PVector loc, vel, unit;
  float speed = 12;

  Bird() {  
    loc = new PVector(int(random(width)), int(random(height)));
    vel = new PVector(speed, 0);
    vel.rotate(random(-PI, PI)); //this is just how heading() describes angles
    unit = new PVector();
    unit = unitVector();
  }

  PVector unitVector() {
    unit = vel.copy();
    unit.normalize();
    return unit;
  }

  void updateLoc() {
    loc.add(vel);
  }
}

```

---

<div class="post-metadata">

**Author:** ![alfrandell](https://avatars.discourse-cdn.com/v4/letter/a/3ec8ea/32.png) [@alfrandell](https://discourse.processing.org/u/alfrandell)\
**Post date:** [April 29, 2020, 7:09pm UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/2 "2020-04-29T19:09:11Z")

</div>

Hi!  
I worked on a 2d boid simulation, and posted it here in the developement section.

I had similar trouble with slow execution. I think that i looked through the boids too many times per time step.  
I used the array list example called flocking in the processing examples.

I am rewriting the program for 3d now, and trying to look through the boids fewer times per time step. I will try to run your program later, to see if i can understand your methods of getting average location and velocity.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [April 29, 2020, 7:36pm UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/3 "2020-04-29T19:36:30Z")

</div>

Try unify the for loops in draw.  
Best would be one for loop only.

When comparing the boid to all others:

Use a nested for loop within the primary one  
but let the inner one start at c+1

So when you start both for loops at 0 it means you compare A to B and later B to A which is unnecessary when done wisely.

When your inner for loop starts at c+1 you avoid this

---

<div class="post-metadata">

**Author:** ![ketchupmustard](https://avatars.discourse-cdn.com/v4/letter/k/47e85d/32.png) [@ketchupmustard](https://discourse.processing.org/u/ketchupmustard)\
**Post date:** [April 30, 2020, 2:12am UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/4 "2020-04-30T02:12:17Z")

</div>

I noticed it runs faster with a smaller bird size. Also was confused about stroke and fill, I think it would be faster with noStroke(), leave all the colour and size to fill().  
Anyways with those changes I can have a reasonable framerate until 700 or so.  
_changed code above with these changes_

I think one of my fundamental questions is, for ex:  
What is the difference in efficiency between implementing two loops or one…

```auto
for array
   get num
for array
   do other stuff

   

```

_vs._

```auto
for array
   get num
   do other stuff

```

---

<div class="post-metadata">

**Author:** ![ketchupmustard](https://avatars.discourse-cdn.com/v4/letter/k/47e85d/32.png) [@ketchupmustard](https://discourse.processing.org/u/ketchupmustard)\
**Post date:** [April 30, 2020, 2:18am UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/5 "2020-04-30T02:18:03Z")

</div>

Thanks! I’ll take some time to look at this. Yeah I’d also like to do a 3D one, eventually.

---

<div class="post-metadata">

**Author:** ![ketchupmustard](https://avatars.discourse-cdn.com/v4/letter/k/47e85d/32.png) [@ketchupmustard](https://discourse.processing.org/u/ketchupmustard)\
**Post date:** [April 30, 2020, 2:27am UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/6 "2020-04-30T02:27:45Z")

</div>

Thanks! I’ll look into this!

---

<div class="post-metadata">

**Author:** ![micycle](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micycle/32/201_2.png) [@micycle](https://discourse.processing.org/u/micycle)\
**Post date:** [April 30, 2020, 8:33am UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/7 "2020-04-30T08:33:19Z")

</div>

- Use FX2D mode: `fullScreen(FX2D);`

- Put calculation code in a separate method and [thread](https://processing.org/reference/thread_.html) the method.

- If you are content for boids to be of size 1x1 pixel, writing the pixel array directly is much faster than calling `rect()` or `ellipse()` to draw boids.

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/1/17b22f67c58ec60b9e8f2e9cc3c40dcb8b9bbfd9.png)  
Pictured: 120000 particles; 4 calc/draw threads drawing at 50fps on a path-following boids sketch using [PThreading](https://github.com/micycle1/PThreading).

---

<div class="post-metadata">

**Author:** ![alfrandell](https://avatars.discourse-cdn.com/v4/letter/a/3ec8ea/32.png) [@alfrandell](https://discourse.processing.org/u/alfrandell)\
**Post date:** [April 30, 2020, 4:15pm UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/8 "2020-04-30T16:15:03Z")

</div>

I have the flocking working well in 3d.  
I made some changes to speed up rendering a lot.

Trying to add a predator to the mix now.

Reviewing my spherical geometry to be able to point my predator.

---

<div class="post-metadata">

**Author:** ![ketchupmustard](https://avatars.discourse-cdn.com/v4/letter/k/47e85d/32.png) [@ketchupmustard](https://discourse.processing.org/u/ketchupmustard)\
**Post date:** [May 3, 2020, 7:14am UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/9 "2020-05-03T07:14:24Z")

</div>

sounds cool. pass on the code if you feel like it.

---

<div class="post-metadata">

**Author:** ![alfrandell](https://avatars.discourse-cdn.com/v4/letter/a/3ec8ea/32.png) [@alfrandell](https://discourse.processing.org/u/alfrandell)\
**Post date:** [May 3, 2020, 1:34pm UTC](https://discourse.processing.org/t/boids-can-i-improve-my-method-efficiency/20256/10 "2020-05-03T13:34:12Z")

</div>

Zipped directory with 3 files  
Balls04.zip

[https://drive.google.com/file/d/11gjozcoZ6uLAe6-zY75I9VzvRg-W\_Hdz/view?usp=drivesdk](https://drive.google.com/file/d/11gjozcoZ6uLAe6-zY75I9VzvRg-W_Hdz/view?usp=drivesdk)

This version uses the video export library, which may cause problems if not installed.
