Week 2 – Rain

Your concept:

Rain always brings me peace; therefore, for this project, I created a scene of rainfall to reflect the feeling I get when it rains. I had some ideas before I settled into this one, such as sunset and sunrise, moving waves, and birds. However, replicating rainfall spoke to me the most. 

I began this assignment by reviewing the materials for this week and watching inspirational videos of things that move. Then, I read a little about the physics behind rainfall, its average acceleration relative to its size, and velocity. I had to do some conversions and basic math to make it logical on a computer screen. For the scene, I used a PNG image for the mountains, a gradient for the sky, rain audio, and some stars to enhance the theme.

Highlight of code:

I tried to make my code neat and clean for this project by creating a different class file and functions whenever possible. The most challenging part of this project was figuring out logical numbers for the line length, acceleration, and velocity so that the rain looks similar to real life. I also had some trouble figuring out how to make sure the lines were straight and not move in any other direction, so I also experimented with it.

class RainDrop {
  constructor(x, y) {
    this.position = createVector(x, y);
    // make the numbers more logical when it comes to rain in pixcels
    this.velocity = createVector(0, random(0.6, 0.9));
    this.acceleration = createVector(0.001, 0.9);
    this.length = random(10, 20);
    this.Colorstrength = random(20, 255); //form od depth
  }
  show() {
    stroke(200, this.Colorstrength);
    //     subtracting x from the length to create a vertical line if i dont it looks weird
    line(
      this.position.x,
      this.position.y,
      this.position.x,
      this.position.y - this.length
    );
  }

  update() {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
  }
}

 

Embedded sketch:

Future work:

While this project satisfies what I have learned so far, in the future, I want to add other factors that affect the acceleration of a raindrop, like the force of air and its density. I also want to add more depth so that the sketch resembles real life and to enhance the experience. Furthermore, I want to loop the sound and create a button for the user to have the power to play and stop the audio.

Resources:

https://hypertextbook.com/facts/2007/EvanKaplan.shtml#:~:text=When%20a%20raindrop%20falls%20to,as%20would%20any%20falling%20body.

https://hypertextbook.com/facts/2007/EvanKaplan.shtml#:~:text=When%20a%20raindrop%20falls%20to,as%20would%20any%20falling%20body.

https://p5js.org/reference/p5.Element/show/

https://p5js.org/reference/p5/lerpColor/

 

Week 2, Palm Date Trees

Since it is around the end of the dates season in the UAE, I have decided to do this assignment related to that. Upon clicking the down arrow button, you can witness the dates falling from the palm trees in a constant acceleration.

It was quite difficult for me to find a video, so here is a photo of date palm trees instead:

The UAE is sending dates into space | Esquire Middle East – The Region's Best Men's Magazine

I limited the acceleration to 3 as I did not want it to speed up too fast as it would seem to be unrealistic. Below is the part of code that shows the dates accelerating when the down arrow button is pressed.

 if (keyCode === DOWN_ARROW) {
  dates.acceleration.y = 0.01;
  dates2.acceleration.y = 0.01;
  dates3.acceleration.y = 0.01;
}

For future improvements, I would allow the user to restart it by clicking the mouse or a button. I also would add different kinds of dates and more of them.

 

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.

Week 2 – Khalifa Alshamsi

Concept:

My concept goes back to Dory from Finding Nemo. She swims around and tries to find Nemo, but she will never find him in this universe I created. With a constant restart whenever she goes off the screen.

Code:

let fish; // Declaring a variable for the fish object

function setup() {
  createCanvas(600, 400); 
  fish = new Fish(); // Initializes the fish object
}

function draw() {
  background(0, 150, 255); // Ocean blue background for a feeling of thr sea
  fish.update(); // Updates the fish's position and movement
  fish.display(); // Display the fish on the canvas
}

class Fish {
  constructor() {
    // Initialize the fish's properties: position, velocity, and acceleration
    this.position = createVector(width / 2, height / 2); // Starts the fish in the middle of the canvas
    this.velocity = createVector(2, 0); // Give the fish an initial velocity to move it to the right
    this.acceleration = createVector(0.01, 0); // Adds a small acceleration to simulate swimming
    this.angle = 0; // Angle for tail movement
  }

  update() {
    // This function updates the fish's position and behavior each frame

    // Simulate natural swimming by adding small random changes to the fish's acceleration
    this.acceleration = createVector(random(-0.01, 0.01), random(-0.01, 0.01));
    
    // Add the acceleration to the velocity to change the fish's speed
    this.velocity.add(this.acceleration);

    // Limits the maximum speed of the fish to make the movement smoother
    this.velocity.limit(3);

    // Updates the fish's position by adding the velocity to it
    this.position.add(this.velocity);

    // If the fish moves off one edge of the canvas, make it reappear on the opposite edge
    if (this.position.x > width) this.position.x = 0; // Reappear on left side if off right
    if (this.position.x < 0) this.position.x = width; // Reappear on right side if off left
    if (this.position.y > height) this.position.y = 0; // Reappear on top if off bottom
    if (this.position.y < 0) this.position.y = height; // Reappear on bottom if off top

    // Creates an oscillating angle for the fish's tail using the sine function
    // The angle swings back and forth, making the tail move naturally
    this.angle = sin(frameCount * 0.1) * PI / 6;
  }

  display() {
    // This function draws the fish on the canvas

    // Set the fill color to blue for Dory's body
    fill(0, 100, 255); // Blue body color
    stroke(0); // Black outlines
    strokeWeight(1); // Set the line thickness for the outline

    push(); // Starts a new drawing state to control the position and rotation of the fish
    translate(this.position.x, this.position.y); // Moves the fish to its current position
    rotate(this.velocity.heading()); // Rotates the fish in the direction of its movement

    // Draws the fish's body as an ellipse
    ellipse(0, 0, 50, 20); // The fish's body (50 pixels wide, 20 pixels tall)

    // Draws the fish's tail as a triangle that moves back and forth
    // Move the tail to the back of the body and rotate it based on the oscillating angle
    push(); // Starts a new drawing state for the tail
    translate(-25, 0); // Moves the tail to the back end of the fish
    rotate(this.angle); // Rotates the tail back and forth
    fill(255, 215, 0); // Yellow color for Dory's tail
    triangle(0, -10, -20, 0, 0, 10); // Draw the tail as a triangle
    pop(); // Restore the previous drawing state for the body

    // Draw Dory's fins (small yellow triangles)
    fill(255, 215, 0); // Yellow fin color
    triangle(10, -10, 20, 0, 10, 10); // Top fin
    triangle(0, 5, -10, 10, -5, 5);   // Bottom fin

    // Draw black markings on the body
    fill(0); // Black for markings
    beginShape(); // Start shape for the black marking
    vertex(0, -10);
    vertex(10, -5);
    vertex(0, 5);
    vertex(-10, 0);
    endShape(CLOSE); // Create a simple black marking shape

    // Draws the fish's eye as a small white circle with a black pupil
    fill(255); // White for the eye
    ellipse(15, -5, 8, 8); // Draw the eye (8x8 pixel circle)
    fill(0); // Black pupil
    ellipse(15, -5, 4, 4); // Draw the pupil (4x4 pixel circle)

    pop(); // Restores the previous drawing state
  }
}

In this simulation, the fish moves by updating its position based on velocity and acceleration, which makes its motion feel natural and fluid, like a real fish swimming. The velocity determines how fast and in which direction the fish swims, while the acceleration adds subtle variations, simulating the fish’s changing speed and slight adjustments in its path. Creating a decent-looking fish was tricky because I had to balance the simplicity of shapes (an ellipse for the body, triangles for the tail, and fins) while ensuring it still resembled a fish, particularly Dory from Finding Nemo. I also added some black markings and a wiggling tail to make the movement more realistic.

One fun complication was ensuring the fish didn’t just swim off the canvas and disappear forever.

// If the fish moves off one edge of the canvas, make it reappear on the opposite edge
if (this.position.x > width) this.position.x = 0; // Reappear on the left side if off the right edge
if (this.position.x < 0) this.position.x = width; // Reappear on the right side if off the left edge
if (this.position.y > height) this.position.y = 0; // Reappear at the top if off the bottom edge
if (this.position.y < 0) this.position.y = height; // Reappear at the bottom if off the top edge

Horizontal boundaries:

If the fish’s x position goes beyond the right edge (this.position.x > width), it reappears at the left edge by setting this.position.x = 0.
Similarly, if it swims past the left edge (this.position.x < 0), it reappears on the right by setting this.position.x = width.

Vertical boundaries:

If the fish swims off the bottom (this.position.y > height), it reappears at the top by setting this.position.y = 0.
If it goes above the top (this.position.y < 0), it reappears at the bottom by setting this.position.y = height.

This wrapping behavior is achieved by checking if the fish’s position exceeds the canvas boundaries and resetting its position to the opposite side, ensuring Dory never swims too far away!

Sketch:

Reflection:

I would love to know more about how to create better-looking shapes without that much struggle; while the end results look like fish, they aren’t the best out there. Also, I would like to add a little controller to make the fish move around.

Resources:

  • https://p5js.org/reference/p5/p5.Vector/
  • https://p5js.org/reference/p5/sin/
  • https://p5js.org/reference/p5/frameCount/#:~:text=A%20Number%20variable%20that%20tracks,in%20draw()%20finishes%20executing.
  • https://forum.processing.org/two/discussion/16493/daniel-shiffman-s-nature-of-code-exercise-1-5.html

Week 2 – Assignment

The Concept

The concept for this project was to create a rain simulation with lightning. Rain is not something we experience here usually but we can simulate it. I don’t have a specific video or picture in mind; I just went to p5 to simulate raindrops, ripples, and lightning.

Code Highlight

function generateLightningBolt() {
lightningBolt = [];
let x = random(width * 0.25, width * 0.75);
let y = 0;
lightningBolt.push(createVector(x, y));
for (let i = 0; i < 8; i++) {
x += random(-30, 30);
y += random(30, 60);
lightningBolt.push(createVector(x, y));
}
}
function drawLightningBolt() {
stroke(200, 200, 255);
strokeWeight(4);
noFill();
beginShape();
for (let i = 0; i < lightningBolt.length; i++) {
vertex(lightningBolt[i].x, lightningBolt[i].y);
}
endShape();
}
function drawSparkles() {
noStroke();
for (let i = 0; i < 20; i++) {
let sparkleX = lightningBolt[lightningBolt.length - 1].x + random(-40, 40);
let sparkleY = lightningBolt[lightningBolt.length - 1].y + random(-40, 40);
fill(255, 255, 255, random(150, 255));
ellipse(sparkleX, sparkleY, random(3, 8), random(3, 8));
}
}

The part of the code that I’m proud of is the lighting. The lighting has two elements, the bolt and the sparkles. For the bolt, I created a random vector starting from a random position at the top of the screen and started adding random values from fixed intervals to that random vector’s coordinates to get the next subsequent random vectors for the zigzag-like pattern of the lighting bolt. Finally, I plotted those vectors by converting each point to a vertex and using the begin and end shape functions to connect those vertices. For the sparkles, I used 20 ellipses the last vertex of the lightning bolt. Each ellipse has a random major and minor axis length fixed between two values.

Sketch

Future Improvements and Reflection

The simulation is a basic representation of rain with a thunderstorm. However, adding sound might make the experience full and realistic. The sounds are mainly for the rain, ripples, and thunder.

Week 2 – Assignment

Concept:

For this week’s assigment, I have decided to get inspired by my favorite season: WINTER (kind of ironic giving the fact that we live in Abu Dhabi). I found myself reminiscing about the snowflakes that I get to see outside my window every time I go back home.

I found this YouTube video for inspiration:

After working for a bit on it, this was the final result:

This is the code:

//SNOWFLAKES ASSIGNMENT 2
//by SP

let snowflakes = [];
let panePadding = 20;

function setup() {
  createCanvas(400, 400);
  noStroke();
}

function draw() {
  setGradient(0, 0, width, height, color(20, 29, 68), color(100, 150, 255));

  // new snowflakes
  let t = frameCount / 60;
  if (random() < 0.05) {
    snowflakes.push(new Snowflake());
  }

  for (let flake of snowflakes) {
    flake.update(t);
    flake.display();
  }

  // remove snowflakes that are off the screen
  snowflakes = snowflakes.filter((flake) => !flake.offScreen());

  drawWindowFrame();
}

class Snowflake {
  constructor() {
    this.posX = random(width);
    this.posY = random(-50, 0); // start slightly off-screen
    this.size = random(5, 12); // size of the snowflake
    this.speed = random(1, 3); // falling speed
    this.drift = random(-0.5, 0.5); // slight drift left or right
    this.angle = random(TWO_PI); // random rotation angle
    this.rotationSpeed = random(-0.01, 0.01); // slight rotation
  }

  update(time) {
    this.posY += this.speed;
    this.posX += this.drift;
    this.angle += this.rotationSpeed;
  }

  display() {
    push();
    translate(this.posX, this.posY);
    rotate(this.angle);
    drawSnowflake(this.size);
    pop();
  }

  offScreen() {
    return this.posY > height;
  }
}

function drawSnowflake(size) {
  stroke(255);
  strokeWeight(2);
  noFill();

  // star-like shapes with lines to represent a snowflakes
  beginShape();
  for (let i = 0; i < 6; i++) {
    let x = cos((TWO_PI * i) / 6) * size;
    let y = sin((TWO_PI * i) / 6) * size;
    line(0, 0, x, y);

    // small branches for each main line
    for (let j = 0.4; j < 1; j += 0.4) {
      let branchX = cos((TWO_PI * i) / 6) * size * j;
      let branchY = sin((TWO_PI * i) / 6) * size * j;
      line(
        branchX,
        branchY,
        branchX + cos((TWO_PI * (i + 0.5)) / 6) * size * 0.2,
        branchY + sin((TWO_PI * (i + 0.5)) / 6) * size * 0.2
      );
      line(
        branchX,
        branchY,
        branchX + cos((TWO_PI * (i - 0.5)) / 6) * size * 0.2,
        branchY + sin((TWO_PI * (i - 0.5)) / 6) * size * 0.2
      );
    }
  }
  endShape(CLOSE);
}

// a vertical gradient
function setGradient(x, y, w, h, c1, c2) {
  for (let i = y; i <= y + h; i++) {
    let inter = map(i, y, y + h, 0, 1);
    let c = lerpColor(c1, c2, inter);
    stroke(c);
    line(x, i, x + w, i);
  }
}

// draw the window frame
function drawWindowFrame() {
  fill(80, 60, 40);
  noStroke();

  let paneWidth = (width - panePadding * 3) / 2;
  let paneHeight = (height - panePadding * 3) / 2;

  rect(0, height / 2 - panePadding / 2, width, panePadding);
  rect(width / 2 - panePadding / 2, 0, panePadding, height);

  rect(0, 0, panePadding, height); // left
  rect(width - panePadding, 0, panePadding, height); // right
  rect(0, 0, width, panePadding); // top
  rect(0, height - panePadding, width, panePadding); // bottom
}

The code that I am most proud of is the one for the snowflakes. In the beginning, I just created small circles but then I decided to make them look more realistic. It took me a long time but it was worth it because it all worked out in the end.

Reflection and ideas for future work or improvements:

Overall, I think I did a good job. Of course it is not super realistic but we are slowly getting there. For the future, I would like to recreate the entire scene and add a table next to the window.

Week 2- Pigeon Feeding Simulation

Concept:
In this assignment, I created an interactive scene where pigeons wander around a gray ground (representing something like a park or city square) searching for food. I added two trees on either side of the canvas, and when I click on them, leaves fall and disappear once they hit the ground. The pigeons move toward randomly placed food, and after one of them reaches the food, a new piece of food appears in a different spot. The goal was to simulate natural pigeon behavior and add a fun, interactive element with the falling leaves, all while using vector-based physics to bring the motion to life.

Code Highlight:
One part of the code I’m really happy with is the falling leaves interaction:

function mousePressed() {
  for (let i = 0; i < treePositions.length; i++) {
    let treePos = treePositions[i];
    // Check if the mouse click is within the tree's area
    if (dist(mouseX, mouseY, treePos.x, treePos.y) < 75) {
      // Generate falling leaves from the clicked tree
      for (let j = 0; j < 10; j++) {
        leaves.push({
          position: createVector(treePos.x + random(-20, 20), treePos.y),
          velocity: createVector(random(-1, 1), random(1, 3)) // Falling leaves
        });
      }
    }
  }
}

This part of the code is what handles the falling leaves when you click on a tree. When the user clicks near one of the trees the code checks if the click is within range using the dist() function to measure distance. If it is it triggers a loop that generates 10 leaves each with random positions and velocities so they fall in a natural way. The leaves then get added to an array so they can be drawn and moved across the screen.

I’m really proud of this because it was the part I struggled with the most. Figuring out how to create that random natural-looking motion for the leaves and getting the click interaction to work properly took some effort but it adds a lot of life to the scene!

Embedded Sketch: 


Reflection and Ideas for Future Work:
Looking back, I’m really happy with how the pigeons’ movement and the interactive leaves turned out. It’s a fun and dynamic scene, but I have a few ideas for improvements and future work:

Perlin Noise for the Ground: I want to add Perlin noise to the ground to give it texture, making it look like dirt or pavement instead of just flat gray.

More Realistic Pigeon Behavior: I’d like to implement flocking behavior so the pigeons move together in a more natural way, like real pigeons do.

Tree Sway and Better Leaves: I think it would be cool to make the trees sway slightly when the leaves fall and vary the size and speed of the leaves for more realism.

Animated Pigeons: Adding animations for the pigeons, like walking or pecking, would make them feel more alive.

Week 2- Maracas Beach

Concept:

As a true island girl, the beach has always held a special place in my heart. It’s not just one of my favourite places in the world; it’s where I find peace and calm. There’s something really magical about being at the beach at night—when the darkness hides your view, but you can still feel the water, hear the rhythm of the waves, and see the moon reflected on the surface. This inspired me to create an ocean scene for this project, with waves at the height of their movement, each with its own unique personality through acceleration.

https://www.youtube.com/watch?v=kT-f2mfNL7s

Embedded Sketch:

Key Features:

In my code, acceleration controls how fast the waves move. You can increase or decrease the speed by pressing the right or left arrow keys:

Pressing the right arrow increases acceleration, making the waves move faster.

Pressing the left arrow decreases acceleration, slowing the waves down.

The movement is smooth because acceleration gradually adjusts the wave speed rather than changing it instantly, making the effect feel more natural. This simulates a build-up or reduction in wave intensity, similar to real ocean waves building up momentum.

Highlight of Code:

One of the most rewarding aspects of this project was simulating the moon’s gravitational pull on the waves. I’m particularly proud of how I captured the subtle way the waves respond to the moon’s slow journey across the sky. The moon’s movement mimics the natural pull of gravity, affecting the height and behaviour of the waves as they interact.

// Slow down the moon's movement, simulating gravitational influence
moonX = map(noise(frameCount * 0.005), 0, 1, 0, width);  // Slow, subtle horizontal movement

// Slightly adjust wave height based on moon's horizontal position (gravity effect)
let gravitationalEffect = map(moonX, 0, width, -20, 20);  // Subtle effect
let y = noise(frameCount * noiseSpeed + i + j) * noiseHeight + noiseY + offsetY + gravitationalEffect;

Reflection and Future Work:

Though the project didn’t quite reach the full vision I had in mind, I’m proud of how it turned out. I originally hoped to simulate waves crashing onto the shore and to add more elements like sound and depth to the sketch. These are definitely areas I plan to improve on in future iterations, but I feel this piece captures the essence of the ocean that I love so much.

 

Falling Leaves in Autumn – Week 2

Concept

I’ve always enjoyed traveling to Europe during autumn. The sight of trees with almost yellow leaves fills me with a sense of calm and nostalgia. As I walk through parks and streets, the leaves gently falling to the ground create a serene atmosphere. Inspired by this, I decided to simulate the motion of falling leaves in my sketch. I wanted to capture how some leaves fall straight down due to gravity, while others drift to the right or left because of the wind. My goal was to recreate this natural motion using code, focusing on how gravity and wind impact the leaves’ movement.

Video Inspiration

I had initially hoped to use a video I took during my travels, but I couldn’t find one. So, I searched online and found a video that inspired this design.

Highlight of the Code

One part of the code I’m particularly proud of is how I simulate the wind and gravity forces. In the sketch, each leaf is given a slight variation in fall speed, which makes their movement feel more natural. Here’s a snippet:

 
// Loop through all the leaves and apply forces, update positions, and display them
for (let leaf of leaves) {
  // Apply gravity force to the leaf (fallSpeed controls how fast it falls)
  leaf.applyForce(createVector(0, leaf.fallSpeed * 0.1)); 
  
  // Random wind strength to add lateral movement (drift) to the leaf
  let windStrength = random(0, 0.05); 
  // Apply wind force in the direction determined by the leaf's drift
  leaf.applyForce(createVector(windStrength * leaf.drift, 0));

In this section, I applied gravity (downward force) and wind (side-to-side force) to each leaf. The random factor in wind strength and leaf drift direction gives the scene a more dynamic and organic feel.

Embedded Sketch

Reflection and Ideas for Future Work

Working on this sketch was both fun and calming. I was able to simulate the movement of the leaves quite effectively using acceleration, gravity, and wind forces. In the future, I’d love to add more interactivity to this simulation. For example, the wind could change based on mouse movements, or the leaves might react differently depending on where they fall. Another idea is to vary the leaf shapes or introduce different weather elements, like rain or snow, for a more complex autumn scene.

P5.js Full Code and Sketch

https://editor.p5js.org/maryamalmatrooshi/sketches/8tY74Enmr

Week 1: Reading Response

In this week’s reading “The Computational Beauty of Nature”, I came across many scientific analogies that have widened my views on nature. Before this reading, I would always look at things from a further perspective and not really think deeply of every object around me and its particular details. Just like the author mentions, the roles of ants in every ant colony would usually be similar, but every ant is unique to its identity and behaves differently despite working on the same task.

It is very fascinating that the reductionist approach can be applied in the computing world. We have had many simulations built thus far that researchers and scientists have benefited from.