Week #2 – Some birds and a tree

Introduction

To get inspired for this week assignment, I took a walk around the campus. I had many ideas in my mind about what I wanted to do; some of them were about trying to imitate the movement of ants or the light of the sun. Although, something caught my interested when I stumbled upon this view:

That is when I realized what I wanted to do.

The Concept

Once I observed this tree populated by many birds, I wanted to recreate both the movement of the leaves, of the tree, and the path the birds take to reach it. At first, I was intimidated to think about this, since it would be very hard to simulate a tree with moving leaves. Nevertheless, I was intrigued.

To reach a satisfactory conclusion for the project, first I had to make a quick sketch about what I wanted to do:

Mockup
Figure 1. Mock-up of the moving trees and how they are going to move according to region.

From what I analyzed in this sketch, I would have to do the following:

    • Simulate many leaves moving at the same time without lagging the computer.
    • Make a believable movement using velocity and acceleration.
    • Populate, randomly, each region and with a different pattern (that is, how they are going to generate according to the range specified).
    • Understand how the birds will interact after the leaves are populated.

Preparing the scenario

Compared to last week’s assignment, I felt that it was too abstract and needed a bit more of style in order to be more presentable. From this experience, I wanted to avoid what I did previously and improve upon it, thus, I wanted to develop a more “alive” canvas.

For this, I needed to create first the scenario that was in symphony with my then progress done:

Figure 2. Preparing the scenario.

Not only that, but in order to create this “alive” canvas, I also realized we would need audio. So, I extracted the audio from the video I recorded, edited it and then added it to the project:

Figure 3. Preparing the background audio.

The code

According to what we have seen in class at the moment, for this code it was essential to work with vectors. Essentially, the vectors were used for almost everything: The ranges where the leaves spawn, the leaves and the birds.

In order to understand how this is possible, here is a quick explanation of how it works in a sequential order:

    1. Regions are created, manually, with the help of createVector(x,y). These regions are stored in the class Leaves. The reasoning of creating regions is to simulate, as accurate a possible with the limitations of p5.js, the movement of the leaves without creating lag and with enough diversity to create the illusion.
    2. After the regions are set, the leaves now start to spawn in each region. There are a total of 5 different regions and, by default, 80 leaves by group. The leaves themselves are represented by green circles that walk through transparency with the help of the Perlin movement. Not only that, but the leaves move by accelerating forwards and backwards in their region.
    3. After the regions and leaves are spawned, the birds can start appearing. To avoid creating a lot of circles in the screen, I decided to only draw one black circle for the birds. They will appear one by one from either the left or right part of the screen. The bird will select a region, randomly, as the endpoint. As mentioned, the birds are represented as black circles that will appear as medium-sized and will be further decreasing to create the illusion of the bird going inside the tree. Once the size of the bird reaches 0, it will generate another bird.

Important note: In order to simulate all of this believably, I had to lock the frame rate to 10. Since if it left with a default of 60, it will look that the leaves and birds are moving at super speeds.

What I am mostly proud of

I am proud that I could simulate how leaves move (at least partially). This was the most challenging part of this work and the one that needed to be addressed first. I took some examples from the class in order to understand how to create this movement. Although, sometimes due to not understanding how it fully worked, the leaves would go out of the Canva, move weirdly, extremely fast and unnatural or just not show at all (because they were going so fast that our eyes could not perceive the moment it left the screen).

Here is a quick example of the code that I used for the movement of the leaves:

// ----- Move leaves according to region. -----

        for (let i=0; i<amount_of_leaves; i++){
            //Taken from the example taught in class.
            let dir = p5.Vector.sub(this.range1, this.p1_leaves[i]);

            dir.normalize();
            dir.mult(0.05);

            this.acceleration = dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(5);
            this.p1_leaves[i].add(this.velocity);
        }


        for (let i=0; i<amount_of_leaves; i++){
            //Taken from the example taught in class.
            let dir = p5.Vector.sub(this.range2, this.p2_leaves[i]);

            dir.normalize();
            dir.mult(0.05);

            this.acceleration = dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(5);
            this.p2_leaves[i].add(this.velocity);
        }

        
        for (let i=0; i<amount_of_leaves; i++){
            //Taken from the example taught in class.
            let dir = p5.Vector.sub(this.range3, this.p3_leaves[i]);

            dir.normalize();
            dir.mult(0.05);
 
            this.acceleration = dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(5);
            this.p3_leaves[i].add(this.velocity);
        }

Although, I am not very proud by the amount of for statements…

Similarly, for the movement of the birds the code was similar, but easier to understand since I knew how it worked:

fly(rng_number){
      //Decide if the bird on the left or right will flight. After that, decide on the final destination to then apply the motion.
        if (rng_number == 1){
            if (this.final_region_destination == 1){
                this.dir = p5.Vector.sub(leaves.range1, this.bird1);
            } else if (this.final_region_destination == 2){
                this.dir = p5.Vector.sub(leaves.range2, this.bird1);
            } else if (this.final_region_destination == 3){
                this.dir = p5.Vector.sub(leaves.range3, this.bird1);
            } else if (this.final_region_destination == 4){
                this.dir = p5.Vector.sub(leaves.range4, this.bird1);
            }
            
            this.dir.normalize();
            this.dir.mult(0.6);

            this.acceleration = this.dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(10);
            this.bird1.add(this.velocity);

            if (this.t <= 0){
                this.restart();
            }

        }

        else if (rng_number == 2){
            if (this.final_region_destination == 1){
                this.dir = p5.Vector.sub(leaves.range1, this.bird2);
            } else if (this.final_region_destination == 2){
                this.dir = p5.Vector.sub(leaves.range2, this.bird2);
            } else if (this.final_region_destination == 3){
                this.dir = p5.Vector.sub(leaves.range3, this.bird2);
            } else if (this.final_region_destination == 4){
                this.dir = p5.Vector.sub(leaves.range4, this.bird2);
            }
            
            this.dir.normalize();
            this.dir.mult(0.6);

            this.acceleration = this.dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(10);
            this.bird2.add(this.velocity);

            if (this.t <= 0){
                this.restart();
            }

        }

Again, not very proud with how copied and pasted it looks…

The Sketch

So, after all of this explanation, what is the final product? Well, there is the final sketch.

Note: The “white background effect” is intentional. Also, this Canva has background audio, no mouse interactions and a default of 10 frames per second.

Full-screen version: Go to the Full-screen version

Reflection and future improvements

I am mostly happy to how this assignment concluded. I feel that I learned new things about the programming world as well as how to interpret movements in nature. Although, there are some improvements I want to make for future works:

    • Even though this sounds nonsensical, I would like to avoid using too many in-class examples for my codes and challenged myself a bit more with what I can find out of the box.
    • Avoid that the circles accumulate all together if the Canva is left running for a few minutes.

Credits

Some references I used for help are the following:

FrameRate reference: https://p5js.org/reference/p5/frameRate/

Sound reference: http://p5js.org/reference/#/p5.SoundFile

 

And the external programs I used are:

To create the background: GIMP.

To prepare the audio: Audacity.

Leave a Reply

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