Assignment-3 Floating Bubbles

Concept

The assignment was to create a generative artwork using Object-Oriented Programming in p5.js. So for this assignment I wanted to create a bubble generator, such that when a button is pressed, random bubbles generates and floats into different directions.

Inspiration

Acrylic Bubble Wall Aquarium, Packaging Type: Box at best price in Noida

I got inspired by watching a Bubble Wall aquarium. It’s like a magical glass tank where bubbles pop up randomly, creating a beautiful display. So, I wanted to recreate that magic digitally by making bubbles appear randomly on the screen when you press a button.

A highlight of some code that you’re particularly proud of

function mouseClicked() {
  
  // Check if mouse click is within the box
  
  if (mouseX > width / 2 - 50 && mouseX < width / 2 + 50 && mouseY > height - 50 && mouseY < height) {
    
    // Add multiple bubbles to the array
    
    for (let i = 0; i < 50; i++) {
      
      //initialize
      let x = random(width);
      let y = height;
      let speedX = random(-5, 5);
      let speedY = random(-10, -5);
      let col = color(random(255), random(255), random(255));
      let size = random(20,60);
      
      //push it to the array
      bubbles.push(new Bubble(x, y, speedX, speedY, col, size));
    }
  }

Embedded sketch

Reflection and ideas for future work or improvements

For future improvements I want to add more life to the aquarium by adding fishes, plants etc. which will contain interactive elements in them

 

Reading Reflection – Week#3

Chris Crawford challenges our initial understanding of interactivity with a discussion of various definitions of what interactivity is and what it is not. What I found notable in trying to define interactivity is that it is the listening, thinking and speaking between two actors, and not a reaction to an action of one of the actors. Crawford also establishes that interactivity is not two-sided, but rather it is a continuum, where we can establish high and low interactivity and bring an example of the fridge lights to distinguish between these levels.

Here, I disagree with the author’s choice to place the fridge at low interactivity. The fridge light has a very limited number of responses to out actions, meaning either turning on or off, which I would not call interactive. It rather reacts to our actions, just in more than one way. No matter how carefully the fridge “listens”, our how intense it “thinks”, its response is not going to vary unless it is broken in some way, which in turn will remove a component of interactivity and fail to fit in the definition provided in the reading.

However, I would like to further explore if interaction is any different from alternating reactions from two parties engaging in listening, thinking, and speaking. Ultimately, exploring the best forms of interactivity is essential for the user experience, therefore I believe these definitions are crucial for solving interactivity issues without faking it.

Assignment 3: OOP

The task for this assignment was to implement an interactive visual experience using the concepts we learned last week, primarily object-oriented programming and arrays. For this assignment, I wanted to play with the visual perceptions of the audience. I wanted to create a very simple piece, but I also wanted to make it look like the piece has different underlying layers by incorporating a sense of depth. To give the illusion of 3D, I modified how shapes are displayed to include shading and perspective distortion. I introduced a z-axis movement illusion for the shapes. In the draw function, an interactive background changes hue based on mouse position, and shapes are updated and displayed with 3D effects.

class DynamicShape {
  constructor(x, y, size) {
    this.x = x;
    this.y = y;
    this.z = random(-20, 20); // Simulate depth
    this.size = size;
    this.rotationSpeed = random(-0.05, 0.05);
    this.color = color(random(360), 80, 80);
    this.type = random(['square', 'circle', 'triangle']);
  }

  // updating the depth
  update() {
    this.z += random(-1, 1);
    this.adjustSizeBasedOnDepth();
  }

  // displaying different shapes
  display() {
    push();
    translate(this.x, this.y);
    scale(map(this.z, -20, 20, 0.8, 1.2)); 
    rotate(frameCount * this.rotationSpeed);
    fill(this.color);
    noStroke();
    switch (this.type) {
      case 'square':
        rectMode(CENTER);
        rect(0, 0, this.size, this.size);
        break;
      case 'circle':
        ellipseMode(CENTER);
        ellipse(0, 0, this.size, this.size);
        break;
      case 'triangle':
        this.drawTriangle();
        break;
    }
    pop();
  }

  // adjusting the depth
  adjustSizeBasedOnDepth() {
    this.size = map(this.z, -20, 20, 10, 50);
  }

  // drawing the triangle
  drawTriangle() {
    triangle(
      this.size * cos(0), this.size * sin(0),
      this.size * cos(TWO_PI / 3), this.size * sin(TWO_PI / 3),
      this.size * cos(TWO_PI * 2 / 3), this.size * sin(TWO_PI * 2 / 3)
    );
  }
}


// draw fucntion
function draw() {
  drawInteractiveBackground();
  shapes.forEach(shape => {
    shape.update();
    shape.display();
  });
}

 


The most challenging part was for me to figure out the static floral background and how to keep changing the hues to keep track of the depth of the newly created objects. Initially  struggled a bit with the new z-axis movement.

Week 4 Reading Response

Chris Crawford’s elucidation on interactivity, particularly his analogy of it as a conversation between users and systems, introduces a profound reevaluation of our engagement with digital interfaces. This perspective challenges the traditional view of interactivity as mere binary exchanges—inputs and outputs—by imbuing it with a relational, almost human-like quality. The notion that interactivity could harbor the depth and dynamism of a conversation compels us to reconsider the essence of our digital interactions. It suggests that these exchanges are not just about the transmission of information but about building a relationship, a dialogue that evolves with each interaction.

However, while Crawford’s analogy enriches our understanding of interactivity, it also raises several questions about its applicability in the real world. The portrayal of interactivity as a seamless conversation glosses over the inherent complexities and frictions present in human-computer interaction. Real-world interactivity is fraught with misunderstandings, misinterpretations, and a lack of feedback that can disrupt the ideal flow of conversation Crawford imagines. This discrepancy between the ideal and the real prompts a deeper inquiry into how we can design interactive systems that truly embody the conversational model Crawford proposes. Can systems be designed to understand and adapt to the nuanced feedback of users? How do we account for the diverse ways individuals interact with technology?

Moreover, Crawford’s perspective invites us to explore the ethical dimensions of designing interactive systems. If we conceive of interactivity as a conversation, then we must also consider the responsibilities inherent in facilitating these dialogues. How do we ensure that these conversations are inclusive, respectful, and enriching for all participants? In what ways might our interactive systems impose upon, rather than enhance, the autonomy of users?

In reflecting on Crawford’s work, I am both intrigued and skeptical. His vision for interactivity as a conversation between users and systems offers a compelling framework for understanding and enhancing our digital interactions. Yet, it also underscores the need for a critical examination of the assumptions underlying this analogy and the practical challenges of implementing it. As we continue to navigate the evolving landscape of interactive design, Crawford’s insights serve as both inspiration and provocation, urging us to think more deeply about the nature of our digital conversations and the worlds they create.

Reading Reflection – Week#3

Reflection on “The Art of Interactive Design” by Chris Crawford:

After reading Crawford’s work, I found myself thinking about how interactivity is often misunderstood. Crawford compares interactivity to a conversation, where both parties listen, think, and speak. This analogy helped me understand that for interaction to be meaningful, both parties need to actively participate. Crawford also talks about how interactivity is often misused and misunderstood. (Pg 5, 6)

However, I had some questions about Crawford’s perspective. He criticizes traditional media like books and movies for not being interactive enough. But I believe these media still have value because they make us feel and think, even though they don’t interact with us directly. Crawford also seems biased towards interactive design over human factors engineering, which focuses on making tools more efficient for workers.

Another question that came up for me was about the limits of interactivity. Are there times when traditional media offer experiences that can’t be replaced by interactive designs? Overall, reading Crawford’s work made me rethink what interactivity means and how it affects design. It made me consider the importance of both form and function in design processes.

Assignment 3 | Generative art using OOP |Aadil

Concept

I was experimenting with the Circles class that we created in class and thought of some way of generating abstract art by using Circles to draw random lines on the Canvas . I came up with a simple algorithm to generate art : 

1.Create random points
2.Draw a circle with random radiuses around the points (restricted random radiuses)
3.Wherever the center of circle is in another, invert the color
4.Make options to change the frame rate
5.Move the circles randomly by making their speeds random
6.Make sliders to change color
7.At the end draw the paths taken to create something random but intriguing

Each Circle on the canvas would have its own corresponding class ,Whenever a Circle would pass over another, it would change color . The user could also add circles by clicking on the canvas. Initially I had fixed the color to a black background and tried experimenting with different colors of circles and backgrounds . Then I thought – ” Why not create a slider to let the user choose what background color they want according to their preferences ?” This would solve the problem of selecting the best looking background and would add user interactivity as well .

Then came the question of art . What kind of final product would I want ?I wanted the art generated to be random but intriguing . I decided to draw the paths traced by the circle . This was done using a graphics buffer . The entire canvas is emptied but only the buffer remains when the simulation ends . I experimented a bit with the color of the trails generated by the circles and decided to make this color relative to the background(just like the fill color of the circles) . I also tried different strokeWeights for the trails and different alpha values for color to make them more or less transparent . at the end I stuck to using strokeWeight as 1 and alpha value as 150 . 

Sketches 

The following are some interesting sketches that I got by experimenting with color, and strokeWeights and Alpha values for the circle trails 

The kind of sketch that We can get from default setting is like follows:

 

Default setting drawing with Black Background

The background color can also be changed according to what the user wants : 

Same image with yellow background

In short, there are a lot of variation that the user could decide on , the circles while drawing the lines are aesthetically pleasing too :

I had to make a decision of whether or not to display the trail lines when the circles are still there . At the end I decided to keep the trail lines . However, hiding them until the end requires changing just one if-else loop which I have indicated in the commented code .

Sketch

Below is the embedded sketch : 

Try playing with the color values and clicking on the sketch to draw the circles before clicking on end simulation to get the web of lines . Ideally the sketch at the end looks best with a black background

Code that I am proud of 

The Display() function of Circles Class is where the magic happens and this is the part of code that I am most proud of :

display() {
  stroke(255);
  strokeWeight(1);
  fill(150 - get(this.x,this.y)[0],255 - get(this.x,this.y)[1],255 -get(this.x,this.y)[2]); // inverting the color of fill from the color at the center of the circle
  circle(this.x,this.y,this.radius*2);
    // Draw a line segment from previous position to current position onto trails buffer
  
  trails.stroke(255 - get(this.x,this.y)[0],255 - get(this.x,this.y)[1],255 -get(this.x,this.y)[2] ,150);//writes to the trails buffer
   //alpha value is 150
    trails.strokeWeight(1);
    trails.line(this.prevX, this.prevY, this.x, this.y);

    
    // Store current position as previous position for next frame
    this.prevX = this.x;
    this.prevY = this.y;
}

 

The idea of using a graphics buffer called trails to make the trails was very useful . the fill() function in this class inverts the color of fill of the circle from the color of the background at the center of the circle . the trails.stroke and trails.strokeWeight command are at the essence of the final art piece (as illustrated in the picture gallery above) . Changing and experimenting with these values was a big part of this project .

Another part that I am proud of is creating the sliders for color and framerate and the end simulation button as it adds to the user interactivity of the sketch  . 

function setup() {
  createCanvas(400, 400);
  trails=createGraphics(400,400);
  backgroundColor = color(33, 33, 45); // Default background color
  
  //Sliders at the bottom of Canvas
  
  backgroundColorRedSlider = createSlider(0, 255, red(backgroundColor)); // Slider for the red component
  backgroundColorRedSlider.position(10, height + 30);
  backgroundColorRedSlider.style('width', '80px');
  let backgroundColorRedLabel = createDiv('Red');
  backgroundColorRedLabel.position(10, height + 10);
  backgroundColorRedLabel.style('color', '#FF5733'); // Custom color
  backgroundColorRedLabel.style('font-family', 'Arial, sans-serif'); // Custom font
  
  backgroundColorGreenSlider = createSlider(0, 255, green(backgroundColor)); // Slider for the green component
  backgroundColorGreenSlider.position(110, height + 30);
  backgroundColorGreenSlider.style('width', '80px');
  let backgroundColorGreenLabel = createDiv('Green');
  backgroundColorGreenLabel.position(110, height + 10);
  backgroundColorGreenLabel.style('color', '#156F25'); // Custom color
  backgroundColorGreenLabel.style('font-family', 'Arial, sans-serif'); // Custom font
  
  backgroundColorBlueSlider = createSlider(0, 255, blue(backgroundColor)); // Slider for the blue component
  backgroundColorBlueSlider.position(210, height + 30);
  backgroundColorBlueSlider.style('width', '80px');
  let backgroundColorBlueLabel = createDiv('Blue');
  backgroundColorBlueLabel.position(210, height + 10);
  backgroundColorBlueLabel.style('color', '#3366FF'); // Custom color
  backgroundColorBlueLabel.style('font-family', 'Arial, sans-serif'); // Custom font
  
  frameRateSlider = createSlider(10, 150, 70); // Min: 1, Max: 60, Starting value: 30
  frameRateSlider.position(10, height + 80);
  frameRateSlider.style('width', '80px');
  let frameRateLabel = createDiv('Frame Rate');
  frameRateLabel.position(10, height + 60);
  frameRateLabel.style('color', '#560F0F'); // Custom color
  frameRateLabel.style('font-family', 'Arial, sans-serif'); // Custom font
  
  frameRateSlider.position(10, height + 80);
  frameRateSlider.style('width', '80px');
  
  //End simulation button 
  let endButton = createButton('End Simulation');
  endButton.position(10, height + 100);
  endButton.mousePressed(stopSimulation);
  endButton.style('font-family', 'Arial, sans-serif');
  endButton.style('background-color', '#FF5733');
  endButton.style('color', '#ffffff');
  endButton.style('border', 'none');
  endButton.style('padding', '5px 10px');
  endButton.style('border-radius', '5px');
  endButton.style('cursor', 'pointer');

  //Create all required Arrays
  speeds = generateSpeeds(num_of_circles);
  v = generateRandomPoints(num_of_circles); //10 points
  r = createRandomRadiuses(num_of_circles, 30, 20); //(length , max_radius ,min_radius)
  arr_circles = createArrayCircles(v, r); //Create array of Circle objects
}

 

Challenges and Further Ideas

One challenge was thinking about the various variables involved in this sketch and asking questions like- the number of default circles? The range of speed? The framerate? the Background color? How should the trail color relate to the background color? What should be the Stroke weights and alpha values for the trail color? Some of these do not have a right or wrong answer and much depends on user preferences . I factored in user input for some of these and determined the rest by experimenting with what looked good (even the variables determined by the user needed to have a default value that should look good to most people) .

While adding user interactivity solved some of these problems, there is scope for taking even more input from the user in the form of asking for alpha values or Stroke weights that would allow the user to use this as a tool for creating generative art . 

I also had further ideas of changing the colors of the circles at the intersection (the part where they intersect)  rather than changing colors based on the coordinates of the circles center . This would make the “drawing” part perhaps more visually appealing or could be made into an artwork of its own .

Overall Reflections

I am happy with the final result and with the variety of sketches that I got playing around with the transparency and color of the trails drawn by the circle. I learnt a lot about creating sliders and graphicBuffers . This project also taught me the power of OOP – one small change in the circles class affects the entire sketch in drastic ways .  I was looking to implement something based on Perlin noise for the color of the circles if they are to change without any user input but eventually I just decided to stick to the slider mechanism . Replacing the user input with Perlin noise is something I look forward to experimenting with in future projects . 

Reading Reflection – Week 3

We often overlook the audience for whom we create something, a tendency especially noticeable in the tech sphere. The primary focus tends to be on making the code function well, while the ‘thinking’ process is neglected, as the author points out. This mirrors human interaction; understanding the person you are talking with is similar to the concept of being interactive. You should know their personality and truly grasp what they want and like to foster meaningful conversation. I believe the true essence of being ‘interactive’ lies in the ability to engage people by understanding their preferences.

Initially, my view of interactive media was merely as a course that merges art and technology. However, after further reflection, my understanding of interactive media has deepened. Now, I see interactive media as something beyond merely delivering impressive outputs; it is about conveying a message and touching someone’s heart, whether by making them feel happy, interested, or impressed. It gains true significance through the “thinking” process between inputs and outputs. My decision to major in business was driven by a desire to create something meaningful for people. Realizing that interactive media can achieve this objective has made it increasingly appealing to me.

Assignment 3 – “Hot Air Balloons” by Hyein Kim

While brainstorming for my assignment, my initial thoughts centered around creating an art piece featuring several repetitive elements in motion. Suddenly, I recalled an image of Turkey I had seen before, specifically a picture of hot air balloons in Cappadocia. 

https://www.travelandleisure.com/thmb/MbwHC-LaxhJsfeBEBVAYCBrg5wY=/1500×0/filters:no_upscale():max_bytes(150000):strip_icc()/hot-air-balloons-festival-cappadocia-turkey-HOTAIR0605-6d61318b9ac0462d9d20f387e5c7d1a9.jpg

The sight of these balloons, each a different color, struck me as particularly appealing, and I decided to base my art on the concept of hot air balloons moving upwards. This idea aligned perfectly with my original concept of incorporating moving, repetitive elements.

Upon completing the hot air balloon portion of my project, I noticed the background felt somewhat empty, so I decided to make moving clouds in the background. Thus, the combination of clouds and hot air balloons became my final concept.

I started with the hot air balloons by creating a Balloon Class, aiming to generate several balloons simultaneously using the same code. Within this class, I implemented a move() function to enable the balloons to move upwards.

//move Hot Air Balloons
move() {
  this.x = this.x + this.xspeed;
  this.y = this.y + this.yspeed;
}

Next, I used the show() function to draw the hot air balloon.

//draw hot air balloons
  show() {
    strokeWeight(4)
    stroke('black')
    angleMode(DEGREES)
    line(this.x - 100, this.y + 50, this.x - 30, this.y + 183);
    line(this.x + 100, this.y + 50, this.x + 30, this.y + 183);
    fill(this.balloonColor)
    circle(this.x, this.y, 230);
    fill('rgb(172,96,96)')
    rect(this.x - 30, this.y + 180, 60, 40, 10);
    fill(this.highlightColor)
    arc(this.x, this.y, 110, 230, 90, 270)
    arc(this.x, this.y, 110, 230, 270, 90)
  }

To ensure each hot air balloon displayed different colors, I introduced variables like “balloonColor” and “highlightColor,” assigning them random RGB colors. The balloon featured two colors: a primary color and a “highlightColor,” which was derived by adjusting the blue component of the RGB value to complement the primary color.

//Randomize Balloon colors
   let red = random(255);
   let blue = random(255);
   let green = random(255);
   this.balloonColor = color(red, green, blue);
   //Highlight Color in the middle which is similar to the sum of R and B of the main color
   let b = (red + blue / 1.3)
   this.highlightColor = color(red, green, b)

To continually regenerate hot air balloons and ensure upward movement, keeping the canvas filled, I created a reset() function.

//create a new balloon and reset the animation if the hot air balloon reaches the end of the canvas
 reset() {
   if (this.y < -250) {
     this.y = height + 100
     this.yspeed = random(-2, -5)
     this.x = random(width)
     this.xspeed = 0

   }

As mentioned earlier, I wanted to include clouds in the background. Thus, I crafted a separate Cloud Class and utilized similar methods to those in the Balloon Class for showCloud(), moveCloud(), and resetCloud(). The clouds moved from left to right, and their reset function triggered upon reaching the canvas’s right edge. Cloud sizes varied randomly.

//create Cloud Class
class Cloud {
  constructor(cloudx, cloudy, cloudspeedx, cloudspeedy) {
    this.x = cloudx;
    this.y = cloudy;
    this.speedx = cloudspeedx;
    this.speedy = cloudspeedy;
    this.cloudsize = random(100, 200) //randomize cloud size
  }

First I defined a variable “cloudsize” which should be generated randomly between 100 and 200.

//draw clouds with random sizes
showCloud() {
  noStroke()
  fill('rgb(255,255,255)')
  circle(this.x - this.cloudsize/3, this.y, this.cloudsize - this.cloudsize/5)
  circle(this.x, this.y, this.cloudsize)
  circle(this.x + this.cloudsize/3, this.y, this.cloudsize - this.cloudsize/5)
  }

I then utilized “this.cloudsize” within the showCloud() function to render a cloud.

To populate the scene with multiple clouds and hot air balloons, I established arrays for each, allowing for automated element addition up to a predefined number.

let balloons = []; //create balloons array
let clouds = []; //create clouds array

function setup() {
  createCanvas(1000, 1000);
  //create 7 hot air balloons positioned randomly in the canvas with random speed (moving up) and add them to the balloons array
  for (let i = 0; i < 8; i++)
  balloons[i] = new Balloon(random(width), random(height), 0, random (-2, -5))

  //create 9 clouds positioned randomly in the canvas with random speed (moving from left to right) and add them to the clouds array
  for (let i1 = 0; i1 < 10; i1++)
  clouds[i1] = new Cloud(random(width), random(height), random(2, 5), 0)  
}

It was very interesting to learn how to use arrays and classes together to create elements. The process of simultaneously producing multiple elements became significantly simpler. One challenge I encountered while crafting the art piece involved randomizing colors for each air balloon. Initially, I placed the code for randomizing colors in the sketch.js file within the “new Balloon” constructor, which resulted in the color of a single balloon changing randomly each frame. I then realized that I should incorporate this code inside the Balloon Class, utilizing `this.balloonColor` to ensure the randomness of color could be applied specifically to each balloon. Overall, this assignment was highly engaging, and I feel like I gained a considerable amount of knowledge.

Reading Reflection 3 – Pavly Halim

Reflecting on “The Art of Interactive Design,” it feels like embarking on a spirited journey through what makes technology engaging. The author presents a world where interactivity is about the clicks and taps on our devices and the conversation between humans and machines. Imagine sitting with a good friend over coffee, where the exchange of thoughts and ideas flows freely. This book suggests that our gadgets should offer a similar two-way street of communication, a concept that feels revolutionary and glaringly obvious.

There’s a playful yet earnest tone in the author’s argument that nudges us to question the authenticity of our digital interactions. Are we merely following a script laid out by designers, or are we genuinely engaging in a dialogue? This perspective might tilt towards a bias for more profound, meaningful connections over superficial tech encounters, but it’s hard not to be swayed by such a compelling case. It leaves you pondering about the true essence of interactivity and whether our current technology meets that mark or acts as interactive. It’s an invitation to dream up a world where every interaction with technology enriches our lives, making us users and participants in a digital dance of ideas.

Assignment 3 – Pavly Halim

Concept 

The concept of using Perlin noise to simulate natural, fluid motion in the particles is inspired. Perlin noise generates a more natural and organic flow compared to purely random movement, as it ensures smooth transitions and variations. This approach is commonly used in generative art and simulations to mimic natural phenomena like smoke, fire, and flowing water.

Code Highlight 

// Update the particle's position
move() {
  // Calculate a noise value for organic movement
  let noiseValue = noise(this.noiseOffset);
  this.pos.x += map(noiseValue, 0, 1, -1, 1) * this.rate;
  this.pos.y += map(noiseValue, 0, 1, -1, 1) * this.vertRate;
  
  // Wrap the particle around edges to make it looks like space
  if (this.pos.x > width) this.pos.x = 0;
  if (this.pos.x < 0) this.pos.x = width;
  if (this.pos.y > height) this.pos.y = 0;
  if (this.pos.y < 0) this.pos.y = height;
      
  // Increment the noise offset for the next frame
  this.noiseOffset += 0.01;
}

The move() function in the particle system utilizes Perlin noise to simulate organic and fluid motion, creating a natural, lifelike behavior in each particle. By calculating a smoothly varying noise value and mapping it to influence the particle’s velocity, the function ensures each particle moves in a unique, seamless manner that mimics natural phenomena. Additionally, the function incorporates edge wrapping to create a continuous, boundless effect on the canvas, enhancing the illusion of a natural, endless environment. This innovative use of Perlin noise, combined with the edge wrapping technique, sets the function apart by providing a sophisticated method to generate complex, visually appealing animations that evoke the randomness and elegance of the natural world.

Embedded Sketch

Code

let particles = [];

function setup() {
  createCanvas(600, 600);
    // Initialize particles and add them to array
  for (let i = 0; i < 400; i++) {
    particles.push(new Particle());
  }
}

function draw() {
  background(0);
    // Loop through all particles to display and move them
    for (let particle of particles) {
        particle.display();
        particle.move();
    }
}

// Define the Particle class
class Particle {
  constructor() {
    // Set initial position to a random point within the canvas
    this.pos = createVector(random(width), random(height));
    this.size = random(0.5, 2);
    //Set random transparency value
    this.alpha = random(150, 255);
    this.noiseOffset = random(0, 1000);
    this.rate = random(-1, 1); 
    this.vertRate = random(-1, 1); 
  }
  
  // Display the particle on the canvas
  display() {
    noStroke();
    fill(255, this.alpha);
    ellipse(this.pos.x, this.pos.y, this.size);
  }

  // Update the particle's position
  move() {
    // Calculate a noise value for organic movement
    let noiseValue = noise(this.noiseOffset);
    this.pos.x += map(noiseValue, 0, 1, -1, 1) * this.rate;
    this.pos.y += map(noiseValue, 0, 1, -1, 1) * this.vertRate;
    
    // Wrap the particle around edges to make it looks like space
    if (this.pos.x > width) this.pos.x = 0;
    if (this.pos.x < 0) this.pos.x = width;
    if (this.pos.y > height) this.pos.y = 0;
    if (this.pos.y < 0) this.pos.y = height;
        
    // Increment the noise offset for the next frame
    this.noiseOffset += 0.01;
  }
}

 

Reflection

I was creating this particle system with p5.js, especially using Perlin noise for fluid motion. This approach transformed a basic animation into a mesmerizing display that closely mirrors the elegance of natural phenomena. The seamless movement and edge wrapping created an endless, captivating visual experience. This project pushed the boundaries of what I thought possible with code and deepened my appreciation for programming as a form of creative expression.

Future work

Looking ahead, I’m excited to explore further possibilities with this particle system, such as introducing interactions between particles to simulate forces like attraction and repulsion, adding color gradients for a more dynamic visual effect, and experimenting with different noise algorithms to vary the motion patterns.