Week 3 – Assignment

Visualise slow, sine-wave courses being travelled by unseen attractors, creating faint forces comparable to whirlpools that attract and release visible particles (movers) floating around the canvas. These particles leave behind soft glowing trails, and the closer they are to the attractors, the more varied their colours are. The entire landscape has the appearance of a serene, lively garden with petals or lights floating in a mild wind.

Breakdown of the Sketch

Invisible Attractors:  These generate soft swirling forces as they follow sine-wave pathways.

The movers (or particles): Are softly shimmering as they leave traces behind and swirl around the attractors. The invisible attractors affect their movement, and the closer they are to the attractors, the more their colour changes.

Visual Appeal: The doodle has a soothing and attractive appearance thanks to its soft gradients, shimmering particles, vibrant colours, and delicate trails.

let particles = [];
let attractors = [];
let numAttractors = 3;
let numParticles = 200;

function setup() {
  createCanvas(800, 800);
  noStroke();
  
  // Create particles
  for (let i = 0; i < numParticles; i++) {
    particles.push(new Particle(random(width), random(height)));
  }
  
  // Create attractors (moving along sine waves)
  for (let i = 0; i < numAttractors; i++) {
    attractors.push(new Attractor(i * TWO_PI / numAttractors));
  }
}

function draw() {
  background(10, 10, 30, 25); // Fading background for trails
  
  // Update and display attractors
  for (let attractor of attractors) {
    attractor.move();
    attractor.display();
  }
  
  // Update and display particles
  for (let particle of particles) {
    particle.applyAttractors(attractors);
    particle.update();
    particle.display();
  }
}

// Particle class representing each mover
class Particle {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = createVector(0, 0);
    this.acc = createVector(0, 0);
    this.maxSpeed = 2;
  }
  
  applyAttractors(attractors) {
    for (let attractor of attractors) {
      let force = attractor.getAttractionForce(this.pos);
      if (force) {
        this.acc.add(force);
      }
    }
  }
  
  update() {
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.pos.add(this.vel);
    this.acc.mult(0);
  }
  
  display() {
    let glow = map(this.vel.mag(), 0, this.maxSpeed, 150, 255);
    fill(100, 150, 255, glow);
    ellipse(this.pos.x, this.pos.y, 8, 8);
  }
}

// Attractor class
class Attractor {
  constructor(offset) {
    this.offset = offset;  // Offset for sine wave motion
    this.pos = createVector(0, 0);
    this.speed = 0.005;
  }
  
  move() {
    let time = frameCount * this.speed;
    this.pos.x = width / 2 + sin(time + this.offset) * 300;
    this.pos.y = height / 2 + cos(time + this.offset) * 300;
  }
  
  getAttractionForce(particlePos) {
    let force = p5.Vector.sub(this.pos, particlePos);
    let distance = force.mag();
    
    if (distance < 150) { // Attraction radius
      let strength = map(distance, 0, 150, 0.1, 0);
      force.setMag(strength);
      return force;
    }
    return null; // No attraction if too far away
  }
  
  display() {
    noStroke();
    fill(255, 50, 50, 50);
    ellipse(this.pos.x, this.pos.y, 20, 20); // Faint circle for visualization (optional)
  }
}

Highlights
Smooth Attractor Motion + Dynamic Glow: The sketch has a softer, more natural flow since the moving attractors follow a smooth sine-wave pattern. A lovely, gentle visual impression is produced by the glowing effect on the particles, where their brightness varies according to their velocity.

The particles’ colour changes create a mystical atmosphere as they float around, while the invisible attractors generate the whirling forces that draw the particles in and out of their orbits.

fill(100, 150, 255, glow);
ellipse(this.pos.x, this.pos.y, 8, 8);

Thoughts and Suggestions for Future Improvements:

This sketch produces a lovely, lively image that is evocative of drifting petals in a peaceful garden or fireflies. A serene image with flowing patterns is produced by the interaction of the gently lighting particles and the smooth attractor motion.

Future Improvements:

To produce a wider variety of swirling patterns, introduce more intricate movement for the attractor, such as spiral or circular routes.
To provide even more visual depth, adjust the particle’s size and glow intensity according to its distance from the attractor and speed.
For an ethereal, more immersive effect, add minor backdrop gradient transitions (from dark blue to purple, for example).

Difficulties: The task at hand involved harmonising the visual components by achieving a smooth and glowing particle motion without causing visual disarray.

End Result:

 

Week 3: Long Distance

Concept:

The idea behind my code is very personal and meaningful to me. This week’s task was about exploring attraction, repulsion, and movement, but as I worked through it, these concepts began to reflect something much deeper. I wanted to use this project to represent the experience of being far away from my loved ones back home. It’s not just the physical distance or the different time zones that can sometimes make things feel disconnected—it’s also that constant push and pull of being apart but still feeling so closely tied together.

To express this, I created clusters of moving particles. They act as symbols for the intangible but powerful connection I have with the people I care about. Even though we may be separated by distance, the bond we share remains strong and evident, just like the attraction forces at play in the code.

How it Works:

The code features two clusters of 500 particles each, influenced by invisible attractors to mimic gravitational effects. The clusters each represent a person, while the moving particles aim to give them the essence of human beings. The particles move smoothly and realistically, reflecting the attraction forces at play, like love, sadness, and sometimes anger. A connecting line between the clusters adds a sense of unity, and provides an extra touch of visual interest, but it also represents the otherwise invisible attraction and connection between the two people.

Embedded Sketch:

Code I’m Proud Of:

One aspect of the code I’m particularly proud of is the attracted function. This function employs vector math to simulate attraction between particles and attractors. It calculates the force vector, adjusts it based on distance, and applies it as acceleration. This function not only demonstrates a solid understanding of forces but also showcases my ability to translate these principles into code effectively.

class Particle {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = createVector(0, 0);
    this.acc = createVector(0, 0);
    this.mass = 1; // Added mass to simulate the same behavior as the "Mover"
  }

  // Function to apply attraction toward an invisible attractor
  attracted(target) {
    let force = p5.Vector.sub(target, this.pos);
    let distance = constrain(force.mag(), 5, 25); // Limit the distance just like in the original Mover code
    let strength = (1 * this.mass) / (distance * distance);
    force.setMag(strength);
    this.acc.add(force);
  }

  // Update position and velocity
  update() {
    this.vel.add(this.acc);
    this.vel.limit(2); // Limit the speed just like in the original Mover code
    this.pos.add(this.vel);
    this.acc.mult(0); // Reset acceleration after each frame
  }

  // Display the particle as a point
  display() {
    point(this.pos.x, this.pos.y);
  }
}

Reflections and Future Work:

Looking back, I’m proud of how the attraction forces in my project brought the particle clusters to life, creating a dynamic and personal representation of connection despite distance. The way the clusters interact feels meaningful, and the organized code made refining the project easier. For future improvements, I want to explore adding forces like friction, make the experience more interactive with user controls, and experiment with different visual elements.

Solar System: Invisible Attractors and Moving Objects – Week 3

Concept
For this weeks assignment, I wanted to explore how invisible forces like gravity can affect objects in motion. I was inspired by the movement of planets around the sun and how they interact with each other through invisible forces (image below). The sketch creates a solar system-like scene where planets and moons orbit around a sun. I also added some extra forces, like a little bit of randomness (turbulence) to make things feel more alive and natural.

Image Inspiration

Code Highlight
One part of the code I’m really happy with is how I made the sun glow. I used different shades of color and layered circles to make the sun look like it’s shining and radiating light, just like in real life. Here’s the code for that:

// Draw gradient layers for the sun
for (let i = gradientColors.length - 1; i >= 0; i--) {
  fill(gradientColors[i]);
  ellipse(this.pos.x, this.pos.y, this.radius * 2 * (1 - i * 0.2)); // Each layer is slightly smaller
}

// Add outer glow to the sun
for (let i = 0; i < 10; i++) {
  let alpha = map(i, 0, 10, 50, 0); // Make the glow fade out
  fill(255, 153, 51, alpha);
  ellipse(this.pos.x, this.pos.y, this.radius * 2 + i * 15); // Expand glow with each layer
}

Embedded Sketch

Reflection and Future Work
Working on this sketch was really fun, but I did face some challenges. It was tricky to make sure the planets and their moons didn’t overlap or move too fast. For the future, I’d like to add a “repulsion” force so that planets and moons don’t get too close to each other. I also think it would be cool to let people interact with the sketch by clicking on planets or moving them around.

Week 2 – Algae Simulation by Dachi

Sketch:

 

Concept: My project is an interactive digital artwork that simulates the movement and appearance of algae in a swamp environment. Inspired by what I have seen in my home country many times, it aims to capture the flow of algae in a river. I used different methodologies to create a dynamic, visually interesting scene that mimics the organic, flowing nature of algae. By incorporating various elements such as multiple algae clusters, water particles, and background rocks, I tried to recreate a cohesive river like ecosystem.

Inspiration: The inspiration for this project came from my trip to Dashbashi Mountain in Georgia. I saw algae flowing in a river near the waterfall, and it was very pretty, almost from a fantasy world. This happened very recently so it was the first thing that came to mind when I was thinking about this project. This brief encounter with nature became the foundation for my work, as I tried to translate the organic movement of algae and water into an interactive digital format.

IMG_7042 – Short clip of moving Algae

Process of Development: I developed this project iteratively, adding various features and complexities over time:

At first I visualized the algae movement. I realized it had to do something with waves and sinusoidal shapes were first thing that came to my mind. Unfortunately, few hours in implementation I realized assignment specifically asked for acceleration. Soon after implementing acceleration, I realized this movement alone limited me in creating algae flow so I had to go back and forth multiple times to get at result that somewhat resembled the movement while using acceleration. Unfortunately, I did not find any definitive tutorials of such movement. As such this is more of a strand like simulation which I slowly built up, line by line, also looking at other works like hair movement for inspiration, I will mention them in references.

These screenshots are from earlier development of the simulations:

As you can see by adding various parameters to each strand as well as overall cluster, we are able to achieve similar wavy pulsating pattern that algae have. I also added particle systems and noise-based algorithms for water movement (you can see inspiration of this from reference). To enhance the environment, I included rock formations and a sky.  I integrated sliders and toggles for user interaction. Finally, I kept refining values till I achieved desire perfomance and visuals. The simulation is pretty heavy to run and you can expect drastic FPS drops, based on number of strands we are running. Water simulation is a significant culprit here despite multiple scaling that was needed to achieve even that. 

How It Works:

Algae Simulation: I created multiple clusters of algae strands, each with unique properties. I animate each strand using sine waves and apply tapering effects and clustering forces for a more natural-looking movement. I also calculate acceleration and velocity for each strand to simulate fluid dynamics.

Water Effects: I used a particle system to create the illusion of flowing water, with Perlin noise for natural-looking movement. I applied color gradients to enhance the swamp-like appearance. There is also background audio of waterfall that helps the immersion.

Environmental Elements: I drew rocks using noise-based shapes with gradients and added a toggleable sky for depth.

Interactivity: I included multiple sliders that allow users to adjust various parameters in real-time.

If you want to know more about in depth working and how everything is related, it will be better to check out my code as it is commented thoroughly.

Code: 

One piece of code I’m particularly proud of is the function that generates and animates individual algae strands:

function algae(strandPhase, strandLength, strandAmplitude, clusterEndX, clusterPulsePhase) {
  beginShape();
  
  let taperingPoint = taperingPointSlider.value() * strandLength;
  let taperingStrength = taperingStrengthSlider.value();
  
  for (let i = 0; i <= strandLength; i += 10) {
    let x = i;
    let y = 0;
    
    let progress = i / strandLength;
    
    let taperingFactor = 1;
    if (i > taperingPoint) {
      taperingFactor = pow(map(i, taperingPoint, strandLength, 1, 0), taperingStrength);
    }
    
    let currentAmplitude = strandAmplitude * (1 - progress * 0.8) * taperingFactor;
    
    let movementFactor = sin(map(i, 0, strandLength, 0, PI));
    let movement = sin(strandPhase + i * 0.02) * currentAmplitude * movementFactor;
    
    let angle = map(i, 0, strandLength, 0, PI * 2);
    x += cos(angle) * movement;
    y += sin(angle) * movement;
    
    let curvature = sin(i * 0.05 + phase + clusterPulsePhase) * 5 * (1 - progress * 0.8) * taperingFactor;
    y += curvature;
    
    let clusteringForce = map(i, 0, strandLength, 0, 1);
    let increasedClusteringFactor = clusteringFactor + (progress * 0.5);
    x += (clusterEndX - x) * clusteringForce * increasedClusteringFactor;
    
    vertex(x, y);
  }
  endShape();
}

This code incorporates acceleration and velocity calculations to simulate realistic fluid dynamics, creating more natural and unpredictable movement. The function also creates a tapering effect along the strand’s length, generates wave-like movement using sine functions, and applies a clustering force to mimic how algae clumps in water. I’m especially pleased with how it combines mathematical concepts like acceleration, sine waves, and mapping with artistic principles to create a visually appealing and believable representation of algae in motion. The integration of user controls allows for real-time adjustment of parameters like acceleration strength, making the simulation highly interactive and customizable.

Challenges

Balancing visual quality with smooth performance was tricky, especially when animating multiple elements at once. Getting the algae to move naturally in response to water currents took a lot of tweaking. The water particle system was also tough to optimize – I had to find ways to make it look good without slowing everything down. Another challenge was making the user controls useful but not overwhelming.

Reflection:

This project was a good learning experience for me. I enjoyed turning what I saw at Dashbashi Mountain into a digital artwork. It was challenging at times, especially when I had to figure out how to make the algae move realistically. I’m happy with how I combined math and art to create something that looks pretty close to real algae movement. The project helped me improve my coding skills and while it’s not perfect, I’m pleased with how finished product looks.

Future Improvements:

Speed it up: The simulation can be slow, especially with lots of algae strands. I’d try to make it run smoother.
Better water: The water effect is okay, but it could look more realistic.
Add more stuff: Maybe include some fish or bugs to make it feel more like a real ecosystem.

References:

p5.js Web Editor | Blade seaweed copy copy (p5js.org)

p5.js Web Editor | sine wave movement (hair practice) (p5js.org)

p5.js Web Editor | Water Effect (p5js.org)

YouTube

Internet

 

 

 

 

 

 

 

 

 

Week 2 Sketch

Concept:

I recently took on the challenge of simulating the motion of a falling feather in nature using p5.js. The goal was to go beyond a simple straight-down fall and imbue the feather with a sense of personality through its movement, all while controlling it solely through acceleration. I envisioned a feather that gently drifts and rocks side to side as it descends, mimicking the playful dance of a real feather caught in a gentle breeze.

Code Highlight:

One of the aspects I’m particularly proud of is how I implemented the rocking motion coupled with a horizontal boost:

// Apply wind force (horizontal acceleration) with Perlin noise and angle influence
let windDirection = noise(noiseOffset) * 2 - 1; // -1 to 1
featherAx = windForce * windDirection + abs(sin(featherAngle)) * 0.5 * windDirection;

This snippet shows how the feather’s horizontal acceleration (featherAx) is influenced not just by random wind (using Perlin noise) but also by its current angle (featherAngle). The abs(sin(featherAngle)) term provides a boost in the direction of the rotation, making the feather sway more pronouncedly as it rocks. This simple addition significantly enhances the visual appeal and realism of the motion.

Embedded Sketch:

Reflection and Future Work:

I’m quite pleased with how this simulation turned out. The feather’s motion feels natural and captures the essence of its lightness and susceptibility to air currents. However, there’s always room for improvement! Here are some ideas for future exploration:

  • More Realistic Feather Shape: The current U-shape is a simplification. Implementing a more detailed feather shape, perhaps with multiple segments, could add visual interest.

  • Interaction with Wind: It would be interesting to allow the user to interact with the wind, perhaps by blowing on the feather through a microphone or using the mouse to create gusts.

  • 3D Simulation: Extending the simulation to 3D space could open up new possibilities for exploring the feather’s movement in a more immersive environment.

  • Multiple Feathers: Simulating multiple feathers interacting with each other and the wind could create a mesmerizing visual experience.

Raindrop Simulator with Wind

For my project this week I knew I wanted to do something related to water. I decided to pick rain, something I miss when in this country. Below you can see the program I created, and you can view the full code on my GitHub here.

The program is simple, it generates raindrops that will fall down the screen. There are sliders to modify the rain’s density and the wind’s speed “blowing” the rain either left or right. To do this, there is an array containing a Drop object that stores a position, velocity, and acceleration vector, that will update itself when step() is called. In the draw() function, there is a loop to iterate through the rain array to update the position of each raindrop. To simulate wind, the acceleration vector is given an x-value based on the current value of the wind slider. This makes the vector move along the x-axis to emulate wind blowing the rain particles. After updating the position, it will draw a line based on the length of the raindrop and its previous x position. The Drop class can be seen here:

class Drop {
  constructor(vel, acc, angle) {
    this.len = random(10, 15);
    this.pos = createVector(random(width), -this.len);
    //slightly varying velocity so they all dont fall at the same exact speed
    this.vel = createVector(0, random(0.5, vel));
    this.acc = createVector(angle, acc);
  }
  step() {
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    //make sure the drops stay in bounds of screen
    if (this.pos.x > width) {
      this.pos.x = -this.len;
    }
    if (this.pos.x < -this.len) {
      this.pos.x = width;
    }
  }
  show() {
    //draw raindrop
    stroke(209, 255, 251);
    line(
      this.pos.x,
      this.pos.y,
      this.pos.x - this.vel.x,
      this.pos.y - this.len
    );
  }
}

Overall, I don’t think there is much else I can do to improve this program. One idea I had was to try to have an effect such as a ripple when the drop would hit the ground. Perhaps it would also be interesting to try to emulate the rain in three dimensions, which would allow for wind to blow in two different dimensions.

Sketch – Week 2

Concept

I wanted to create realistic clouds as I was inspired by the beautiful skies and sunsets I grew up seeing in Vancouver. I was not able to capture a video myself as Abu Dhabi is relatively cloudless, so I used a video from the internet as a reference point. The clouds were not moving at a constant rate and did not move in only one directions. I used acceleration to achieve this random effect.

Code Snippet

noiseVector = createVector(0, 0);          // Starting position
noiseVelocity = createVector(0.03, 0);     // Initial velocity moves from left to right
noiseAcceleration = createVector(random(-0.005, 0.005), random(-0.005, 0.005)); // Small acceleration for drift


// Update the noise field
noiseVelocity.add(noiseAcceleration);  
noiseVector.sub(noiseVelocity);       
  
// Move noise field slightly in all directions 
noiseAcceleration.x = random(-0.0005, 0.0005);  
noiseAcceleration.y = random(-0.0005, 0.0005);

 Embedded Sketch

Reflections

I had a lot of trial and error with the cloud movement. Using Perlin noise helped create the cloud like shape, but in the video I was referencing, the clouds were moving and changing constantly. I think modifying the acceleration helped create the cloud movement and make it look more natural/random, but I was not able to modify the acceleration a lot as this would make the movement erratic, so the result ended up being more subtle. In the future, I want to look into other ways to modify Perlin noise.

Simulating Butterfly Flutters

Butterfly Flutters

In this project, we simulate the fluttering motion of a butterfly by focusing on how acceleration could be used to control the movement.

Rules

  • A butterfly’s movement is influenced by unpredictable changes in its speed and direction, so we’ll randomize the acceleration over time.
  • While acceleration can be random, the butterfly doesn’t move too fast. We’ll use a damping factor to slow the object down.
  • The butterfly has to stay within the canvas, so we’ll implement boundary conditions to keep it in view.
  • By focusing on irregular accelerations and smooth decelerations, we can simulate the light, erratic fluttering of a butterfly.

Code

I’m particularly proud of how adding slight randomness to the acceleration makes the butterfly feel alive, without the need for overly complex design or physics.

let randomAcc = createVector(random(-1, 1), random(-1, 1));
this.acceleration.add(randomAcc);

// Update velocity based on acceleration
this.velocity.add(this.acceleration);

// Limit velocity to simulate fluttering motion, not too fast
this.velocity.limit(this.maxSpeed);

// Dampen the velocity slightly
this.velocity.mult(0.95);

link to code

Future improvements

  • I could improve the butterfly’s visual design by adding more details to the wings and body.
  • Adding mouse or keyboard interactions could let users “guide” the butterfly around the canvas.
  • Introducing environmental elements like wind or obstacles could add complexity and realism to the simulation.

Week 2 | Just bounce

Visit the sketch here!
Concept and Inspiration

In the second week, we tapped into the world of vectors. I wanted to make something simple that requires speed, velocity, and everything around us with such aspects. Our class starts with bouncing a ball, and I revisited this concept again this time by applying vectors. What I wanted to recreate is a ball object falling into the water and creating this ripple-like effect.

Sketch

How it works

Using vectors, we can have p5.js calculate the speed of the object. The concept of ‘gravity’ here can be attributed to the y-position of the ball. Each time the ball bounces, its y-position should be decreased by cutting it in half. For the bounce to feel smoother, we introduce a bounciness variable that multiplies with the y-position negatively.

// bounce by multiplying the speed by the bounciness
  if (position.y + diameter / 2 > height) {
    position.y = height - diameter / 2;
    speed.y *= -bounciness;
    speed.x *= bounciness;
  }
Challenges faced

The tutorial that I followed only introduced the concept of ‘gravity’ in scalar methods. Extracting this information, I transformed the modes from scalar to vector. It was quite interesting, and quite the challenge!

As I originally mentioned, I wanted to make the ball form ripples when touching a certain height. While creating the ripples itself is a simple task using for-loops, making sure that it stays without being refreshed by the background is a challenge that I still haven’t overcome yet.

I have been trying to implement a few things, but I do not want my code to become overcomplicated. While I still have the time, I’ll try some stuff up to see if fixing this is possible.

Edit: I finally fixed the ripple problem, check it out here.
Resources Used

Bouncing Ball Simulation – Jeff Thompson

Assignment 2- Spiral Repulsion

Concept

For this assignment, I was primarily inspired by the galaxy—a seemingly simple yet profoundly intricate phenomenon in our vast universe. The swirling motion of stars and cosmic dust, the vibrant colors, and the immense scale all evoke a sense of mystery and wonder. Galaxies are both elegant and complex, embodying the balance between chaos and order. This duality inspired me to explore patterns and shapes that reflect the beauty and unpredictability of the cosmos. Through this project, I aimed to capture the essence of the galaxy’s mesmerizing movement and its delicate balance of simplicity and complexity.

In my code, I implemented two key features. The first was the required assessment of movement and acceleration. By pressing the up and down arrow keys, the speed of the particles could be controlled, allowing for a dynamic interaction with the animation. The second feature involved particle interaction through hovering. As the cursor hovers over the particles, they would disperse, creating a sense of disruption and fluid motion in response to user input.

Dark Matter May Not Exist: These Physicists Favor of a New Theory of Gravity

Highlight I’m proud of

Here I was able to create a special class for the particles.

class Particle {
  constructor(vx, vy) {
    this.vx = vx;
    this.vy = vy;
    this.num = 255;
    this.a = 255;
    this.loc = createVector(width / 2, height / 2);  // Start from the center
    this.vel = createVector(0, 0);  
    this.acc = createVector(1, 1);
  }

  update() {
    // Apply acceleration using the acceleration factor
    this.vel.add(this.acc.mult(accelerationFactor));  
    this.loc.add(this.vel);

    // Reset acceleration and limit the velocity for smoother control
    this.acc.mult(0);
    this.vel.limit(0.5);  
  }

  repulse() {
    // Calculate the distance between the particle and the mouse
    let mouse = createVector(mouseX, mouseY);
    let dir = p5.Vector.sub(this.loc, mouse);  
    let distance = dir.mag();  

    if (distance < repulsionRadius) {  // If the particle is within the repulsion radius
      dir.normalize();  // Normalize the direction to get just the direction vector
      let force = map(distance, 0, repulsionRadius, 5, 0);  // Stronger repulsion the closer the particle is
      dir.mult(force);  // Multiply the direction vector by the repulsion force
      this.vel.add(dir);  // Apply the repulsion force to the particle's velocity
    }
  }

  isOutside() {
    // Check if the particle goes outside the canvas
    return (this.loc.x < 0 || this.loc.x > width || this.loc.y < 0 || this.loc.y > height);
  }

  display() {
    // Update acceleration based on the particle's properties and a trigonometric function for spirals
    this.acc = createVector(
      sin(radians(this.vx + this.num / 2)) / 2,
      cos(radians(this.vy - this.num / 2)) / 2
    );

    // Draw the particle with a fade effect
    fill(255, this.a);
    var r = map(this.a, 255, 0, 1, 10);  // Particle size changes as it fades
    ellipse(this.loc.x, this.loc.y, r);

    this.num += map(this.a, 255, 0, 1, 0);  // Update num for smooth spiral motion
    this.a -= 0.1;  // Gradually reduce alpha for a fade-out effect
  }
}

Embedded sketch

Sketch:
 https://editor.p5js.org/mariamalkhoori/sketches/_t5yMvlGp
Reflection and ideas for future work or improvements
  • User Interaction: Add interaction features such as particles reacting to clicks or drag-and-drop functionality.
  • Different Particle Types: Introduce various particle types with distinct behaviors, such as different shapes or sizes.
  • Customizable Motion Patterns: Allow particles to follow different patterns or trajectories, like zig-zags or chaotic paths.
Refrences:
  • https://editor.p5js.org/RonanChang/sketches/S1NQJgbx4
  • https://decodingnature.nyuadim.com/2024/08/28/week-1-fireflies-by-dachi/