Week 9 Assignment – Flocking Behavior

Concept:

I was listening to one of my favorite songs called “Good-bye days” by a Japanese singer called YUI when I got the inspiration for this sketch. This song always reminded me of a summer night when the sun is starting to set and people chilling in an endless green field while trying to catch fireflies, and I thought this might be a fun idea to try to recreate using flocking.

Process/Highlight:

I used all three of the main skills that we learned in class by referring to our class slides as well as the Coding Train’s tutorial, which are:

  1. Alignment — I used this to align boids to their neighboring boids, so that they will all match velocities and also the direction of their movement instead of dispersing.
  2. Cohesion — this feature was what held the boids somewhat loosely together in a group so that they won’t be too spread out and will still somehow manage to stay close to each other.
  3. Separation — this was necessary because while I still wanted my boids to stay close to each other and move in a cohesive way towards a certain direction, I also didn’t want them to clash into each other because in real life, fireflies keep their distances from each other. This added a sort of “repelling” behavior amongst the boids.

A special feature I added was limiting the space of where the boids can travel to, which I did so by adding the “constrainToArea” function within the “Boid” class. At first, I made the area so that boids will only be able to travel in the upper half of the canvas, but this seemed too rectangular because the boid particles were very specifically outlining the rectangular area, so I modified it so that they’ll be active in 2/3 of the canvas area.

constrainToArea(x1, y1, x2, y2) {
  this.position.x = constrain(this.position.x, x1, x2);
  this.position.y = constrain(this.position.y, y1, y2);
}
...

Then I adjusted the following code elements in class Boid so that the boids were behaving in a way I wanted them to:

class Boid {
  constructor() {
    this.position = createVector(random(width), random(height));
    this.velocity = p5.Vector.random2D();
    this.velocity.setMag(random(2, 4));
    this.acceleration = createVector();
    this.maxForce = 0.6;
    this.maxSpeed = 10;
    this.repulsionRange = 70; // Distance to start separation
    this.alignmentRange = 90; // Distance for alignment
    this.cohesionStrength = 0.8; // Strength of cohesion behavior
    this.separationStrength = 1; // Strength of separation behavior
  }

For example, adjusting the this.maxForce and this.maxSpeed by increasing their values helped the particles to show their repulsion from the mouse cursor much clearer, as well as increasing the this.repulsionRange and this.alignementRange.

I was happy with the above values because they showed my desired picture when I simulated it, so I decided to stick with them. Then I simply added a background image that I got from this link to show that blue sky, summer night background, and changed the color of my boids to yellow so that they will be like fireflies.

Final Sketch:

And here’s the final sketch. Click on the sketch screen once and then feel free to move your mouse cursor around to observe how the boids repel from it!

Reflection: 

Next time I’d like to add a character to the mouse cursor so that it’ll be like a character chasing down the fireflies but the fireflies just flying away from her, just like a scene that could be in a Ghibli movie!

Additional Change:

After hearing professor’s feedback in class about adding trails to show the “glow” of the fireflies better, I added the below snippet of code:

class Boid {
...
    this.history = []; // New property to store position history

...

    // Store the current position in history
    this.history.push(createVector(this.position.x, this.position.y));

    // Limit the history length to control the trail length
    if (this.history.length > 50) {
      this.history.shift();
    }

...

  show() {
    noStroke();
    fill(255, 255, 102, 24); // Adjust the alpha value for transparency

    for (let pos of this.history) {
      ellipse(pos.x, pos.y, 6, 6); // Adjust the size of the ellipse
    }
  }

...

}

I adjusted the size and the transparency of the ellipse trail as I saw fit, and I’m really pleased with the outcome!

Leave a Reply

Your email address will not be published. Required fields are marked *