Week 3: OOP and Generative Art

Concept

For this assignment, I wanted to build on top of ideas I thought of last week, particularly leveraging organic shapes in nature to produce generative, and *somewhat* interactive art. I especially wanted to dabble with mathematics and its ability to generate aesthetic abstractions and animations. To that latter point, my mind immediately shifted to the complex and patterned loops defined by parametric equations. I came across Re-generate, a work by Akshan Ish, that utilizes shapes governed by parametric relations, and was immediately inspired to adopt the concept. As I thought about possible shapes I wanted to recreate, I thought of butterfly shapes, and just as I hoped, I found a parametric curve that modeled them. With the mathematics by my side, I was now ready to translate it into a p5.js  animated, generative sketch.

Process, Challenges, and Implementation

I created a butterfly class from which butterfly objects would be instantiated. The main attributes specified the starting point coordinates, the angle from the x-axis in the Cartesian plane used to control the drawing of the wings, the parameters that control the magnitude of the radius, the color of the stroke (which is randomized from a given color palette, and the angle that controls the rotation of the Cartesian plane so that different objects will be drawn from a different starting point. Having the explicit equations for the x and the y parameters facilitated things for me as I would have had to derive them myself otherwise. One thing I had struggled with a little bit here was making the curve draw incrementally over time. After realizing that the angle determines how much of the curve is drawn, it became evident that incrementing the angle in every frame by a little bit and drawing up to that point would essentially produce that effect.

class Butterfly {
  constructor(x, y) {
    this.x = x; // starting x location 
    this.y = y; // starting y location 
    this.theta = 0; // current drawing angle 
    // choose a random color from the color palette for the butterfly animation
    this.color = random([
      color("#7c9eb7"),
      color("#c5d6db"),
      color("#ffd3d7"),
      color("#ffc20c"),
    ]);
    // controlling hyperparameters for the butterfly shape 
    this.b = random(3, 6);
    this.a = random([4, 6]); 
    // variable controlling the rotation of the object 
    this.angleRot = random([-1, 1]) * random([0, 1, 2, 3, 4]);
  }

  drawButterfly() {
    push(); // save the current drawing state 
    translate(this.x, this.y); // move the origin to the object's position
    stroke(this.color); // set the stroke color based on the chosen color 
    rotate((this.angleRot * PI) / 4); // rotate the object 
    noFill(); 
    strokeWeight(1);
    beginShape();
    // draw the curve 
    for (let i = 0; i <= this.theta; i += 0.1) {
      // calculate the radius based on the parameteric equation for the butterfly curve 
      let r =
        exp(sin(i)) -
         this.a * cos(4 * i) +
        pow(sin((1 / this.b) * 12 * (2 * i - PI)), 5);
      // calculate x and y position of the curve 
      let x = r * cos(i) * random(10, 20);
      let y = r * sin(i) * random(10, 20);
      // draw circle 
      curveVertex(x, y, r);
    }
    endShape();
    this.theta += 0.01; // increment theta for animation 

    pop(); // restore original sketch state 
  }

  finished() {
    return this.theta > TWO_PI; // to indicate that the drawing of the shape has ended 
  }
}

When the sketch is played, a Butterfly object is inserted into a global array of butterflies. The user can add objects to the sketch at any location by pressing the mouse. Once a butterfly object is drawn in full, it is deleted and another object is instantiated in its place at a random location. One issue I encountered was that the more objects I created by pressing the mouse, the more overcrowded the sketch became. I tackled the issue by placing bounds on the length of the butterfly array so that objects are only re-instantiated only if the array size does not hit a certain maximum size.

Admittedly, I had a lot of fun playing with different shapes and introducing randomness and Perlin noise into the sketch. I found that different methods produced different emergent qualities. For instance, curves with randomness were akin to children’s drawings on a blackboard, but with Perlin noise, they were more seamless and refined. Circles with randomness had a glowing radiance that reminded me of fireworks or diamonds. The use of circles with Perlin noise, however, elicited a more abstract effect and almost had a level of depth to it that I liked. Here are images from the four experiments below.

3.1 – Lines with Perlin noise 3.2 – Circles with randomness3.3 – Lines with randomness3.4 – Cirlces with Perlin noise 

Embedded Sketch

I am embedding the sketch that I liked the most. The p5.js sketch for each of these can be found by clicking the URL linked with the caption below each one of the images above.

Reflections and Ideas for the Future

What I loved about the process of creating these sketches was how it naturally flowed from my earlier projects and how it amalgamated the power of mathematics to create something generative and abstract yet still organic and nature-inspired. I want to continue experimenting with different polar curves and to continue abstracting my work and learning more advanced animation strategies.

Week 3: Interactivity Reading

This reading showed me a perspective of interactivity that I had never thought of before. Crawford has given me a new viewpoint that interactivity has certain categories that need to be there for the piece to really be interactive.

The way that Crawford reiterates on the conversation example makes it seem very relatable and made my understanding of interactivity clearer. He also proceeds to give us examples of interactivity and scales them on his “10-point Crawford scale of interactivity”, which shows us how interactive of a piece it is.

Assignment 3: Generative Art using OOPS, Functions & Arrray’s

Concept: My generative art created using P5.js presents a captivating display of colorful circles arranged in a dynamic pattern using OOPS, Arrays and Functions. I have integrated few interactive functions to make it more interesting. Inspired by the interplay of randomness and user interaction as discussed in class, this artwork embodies the concept of controlled chaos.

Main Inspiration:

At initial phase: At first, I had the idea to create artwork like the one in the video, but instead of using curves, I wanted to use circles. Each circle in my artwork has its own size, color gradient, and movement, which all come together to make the overall picture interesting. I added an interactive feature so people can join in and make the artwork themselves by clicking the mouse to add new circles. This makes the artwork more dynamic and engaging. The colors of the circles change gradually based on their position on the screen, which gives the artwork depth and liveliness. Additionally, each circle rotates at its own speed, adding a sense of flow and motion. Overall, my artwork demonstrates how randomness can be controlled to create harmony, inviting viewers to appreciate the beauty of unpredictability.

[Initial Output] This is how it looks! Try tapping anywhere in canvas to create more fun circles.. 

Initial Art Code:

let circles = [];

function setup() {
  createCanvas(600, 600);
  
  // Create an initial set of circles
  for (let i = 0; i < 50; i++) {
    let circle = new Circle(random(width), random(height), random(10, 50));
    circles.push(circle);
  }
}

function draw() {
  background(255);

  // Update and display each circle
  for (let circle of circles) {
    circle.update();
    circle.display();
  }
}

function mousePressed() {
  // Add a new circle at the mouse position when clicked
  let newCircle = new Circle(mouseX, mouseY, random(10, 50));
  circles.push(newCircle);
}

// Circle class definition
class Circle {
  constructor(x, y, diameter) {
    this.x = x;
    this.y = y;
    this.diameter = diameter;
    this.color1 = color(random(255), random(255), random(255));
    this.color2 = color(random(255), random(255), random(255));
    this.speedX = random(-2, 2);
    this.speedY = random(-2, 2);
    this.rotation = random(TWO_PI); // Random initial rotation
    this.rotationSpeed = random(-0.05, 0.05); // Random rotation speed
  }

  update() {
    // Move the circle
    this.x += this.speedX;
    this.y += this.speedY;

    // Bounce off the walls
    if (this.x > width || this.x < 0) {
      this.speedX *= -1;
    }
    if (this.y > height || this.y < 0) {
      this.speedY *= -1;
    }

    // Update rotation
    this.rotation += this.rotationSpeed;
  }

  display() {
    // Draw the circle with color gradient and rotation
    let gradientColor = lerpColor(this.color1, this.color2, map(this.y, 0, height, 0, 1));
    fill(gradientColor);
    noStroke();
    push();
    translate(this.x, this.y);
    rotate(this.rotation);
    ellipse(0, 0, this.diameter, this.diameter);
    pop();
  }
}

I felt that my artwork needed some additional features to make it more engaging, so I decided to incorporate three new elements:

1. Interactive Drawing: Now, users can click and drag their mouse to draw colorful circles directly onto the canvas. This adds an interactive dimension to the artwork, allowing people to actively participate in its creation.

2.Dynamic Color Palette: To enhance visual appeal, I introduced a dynamic color palette. Each circle is filled with colors randomly selected from a predefined palette, adding variety and vibrancy to the overall composition.

3.Transparency Effect: To create a sense of depth and visual interest, I implemented a transparency effect. The transparency of each circle varies based on its diameter, resulting in a captivating depth effect as circles overlap on the canvas.

Final Output (Tap and drag the mouse anywhere in the canvas)

This is how it looks if the user added more circles:

Final Code:

let circles = [];
let colorPalette = ['#FFC857', '#F4A35F', '#EE6C4D', '#F95738', '#FF5733', '#FF355E', '#D40C6B', '#7A00FF', '#0045FF', '#0088FF']; //Creating an array filled with color palettes. 

function setup() {
  createCanvas(800, 600);
  
  // Creating an initial set of circles
  for (let i = 0; i < 100; i++) {
    let x = random(width);
    let y = random(height);
    let diameter = random(10, 50);
    let colorIndex = floor(random(colorPalette.length));
    let circle = new Circle(x, y, diameter, colorPalette[colorIndex]);
    circles.push(circle);
  }
  
  // Adding interactive features (just need to tap and drag)
  background(0);
  textAlign(CENTER, CENTER);
  textSize(36);
  fill(255);
  text("Click and drag to draw!", width / 2, height / 2);
}

function draw() {
  // Updating and displaying each circle
  for (let circle of circles) {
    circle.update();
    circle.display();
  }
}

function mouseDragged() {
  // Add a new circle at the mouse position when dragged
  let diameter = random(10, 50);
  let colorIndex = floor(random(colorPalette.length));
  let circle = new Circle(mouseX, mouseY, diameter, colorPalette[colorIndex]);
  circles.push(circle);
}

// Defining Circle class 
class Circle {
  constructor(x, y, diameter, color) {
    this.x = x;
    this.y = y;
    this.diameter = diameter;
    this.color = color;
    this.speedX = random(-2, 2);
    this.speedY = random(-2, 2);
    this.rotation = random(TWO_PI); // Random initial rotation
    this.rotationSpeed = random(-0.05, 0.05); // Random rotation speed
  }

  update() {
    // Moving the circle
    this.x += this.speedX;
    this.y += this.speedY;

    // Bouncing off the walls
    if (this.x > width || this.x < 0) {
      this.speedX *= -1;
    }
    if (this.y > height || this.y < 0) {
      this.speedY *= -1;
    }

    // Updating rotaion
    this.rotation += this.rotationSpeed;
  }

  display() {
    // Drawing the circle with rotation and transparency effect
    push();
    translate(this.x, this.y);
    rotate(this.rotation);
    fill(this.color);
    noStroke();
    let alpha = map(this.diameter, 10, 50, 50, 200); 
    // Varrying transparency based on diameter
    fill(red(this.color), green(this.color), blue(this.color), alpha);
    ellipse(0, 0, this.diameter, this.diameter);
    pop();
  }
}

Code I’m proud of: Initially, I found implementing the transparency effect challenging in my artwork. Understanding how to vary the transparency based on the diameter of each circle was tricky. However, I managed to overcome this difficulty by experimenting with the map() function in the display() method of the Circle class. By mapping the diameter of each circle to a range of transparency values, I was able to achieve the desired effect. This involved adjusting the parameters of the map() function until I achieved the desired transparency levels, ultimately resulting in a visually appealing depth effect as circles overlapped on the canvas. Overall, successfully implementing this feature added an extra dimension to my artwork that I’m proud of.

Additional Art Work: With Valentine’s Day approaching, I decided to enhance my artwork by making some adjustments to the code. Here’s the updated look!

Here’s the code for the Valentine’s Day themed artwork:

let hearts = [];
let colorPalette = ['#FF4D6D', '#FF6381', '#FF7992', '#FF8BA3', '#FFA3B5', '#FFBFC7', '#FFD1D9', '#FFEDF2'];

function setup() {
  createCanvas(800, 600);
  
  // Addinng a sweet message
  background(255);
  textAlign(CENTER, CENTER);
  textSize(36);
  fill(150);
  text("Happy Valentine's Day!", width / 2, height / 2 - 50);
  text("Click and drag to create love!", width / 2, height / 2 + 50);
}

function draw() {
  // Updating and displaying each heart
  for (let heart of hearts) {
    heart.update();
    heart.display();
  }
}

function mouseDragged() {
  // Adding a new heart at the mouse position when dragged
  let size = random(30, 100);
  let colorIndex = floor(random(colorPalette.length));
  let heart = new Heart(mouseX, mouseY, size, colorPalette[colorIndex]);
  hearts.push(heart);
}

// Heart class definition
class Heart {
  constructor(x, y, size, color) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.color = color;
    this.speedX = random(-2, 2);
    this.speedY = random(-2, 2);
    this.rotation = random(TWO_PI); // Random initial rotation
    this.rotationSpeed = random(-0.05, 0.05); // Random rotation speed
  }

  update() {
    // Moving the heart
    this.x += this.speedX;
    this.y += this.speedY;

    // Bounce off the walls
    if (this.x > width || this.x < 0) {
      this.speedX *= -1;
    }
    if (this.y > height || this.y < 0) {
      this.speedY *= -1;
    }

    // Update rotation
    this.rotation += this.rotationSpeed;
  }

  display() {
    // Drawing the heart with rotation and transparency effect
    push();
    translate(this.x, this.y);
    rotate(this.rotation);
    fill(this.color);
    noStroke();
    let alpha = map(this.size, 30, 100, 50, 200); // Vary transparency based on size
    fill(red(this.color), green(this.color), blue(this.color), alpha);
    beginShape();
    vertex(0, -this.size / 2);
    bezierVertex(this.size / 2, -this.size / 2, this.size, 0, 0, this.size);
    bezierVertex(-this.size, 0, -this.size / 2, -this.size / 2, 0, -this.size / 2);
    endShape(CLOSE);
    pop();
  }
}

Conclusion:  In conclusion, my inspired Bouncing Circles Art and Valentine’s Day-artwork successfully integrates the principles of generative art, interactive elements, and dynamic features using circles. The addition of an interactive drawing feature, a dynamic color palette, and a transparency effect enhances the overall aesthetic appeal, allowing users to engage with the artwork in a meaningful way. To speak more about the Valentines artwork,  the fusion of vibrant colors and interactive drawing adds a festive touch, making it suitable for the Valentine’s Day theme.

While I am pleased with the outcome, there are areas for potential improvement. One aspect to consider is enhancing user interaction further by introducing additional interactive features or refining existing ones to make the artwork even more engaging. Additionally, exploring different color palettes and experimenting with more complex patterns could elevate the visual impact of the artwork. Overall, this project has provided valuable insights and opportunities for growth, and I look forward to continuing to refine my skills and expand my creative horizons in future projects.

Week 3 Reading Response: The Art of Interactive Design

In this chapter, Chris Crawford sets about to define the murky concept of ‘interactivity’. As Crawford rightly mentions, interactivity has become the buzzword of the Web age, prompting much corporate marketing based on the notion of interactivity, even when it doesn’t make sense. Thus, it is important to set a clear definition of interactivity and what constitutes as interactive.

I feel Crawford’s “Listening, Thinking, Speaking” definition is definitely a good place to start, but while trying to exclude things that are definitely not interactive, it may exclude things that are conventionally seen as interactive. After all, so-called smart lamps, for example, do not “think” much (I am talking about the most basic ones, such as the ones that respond to clapping), yet they could be classified as interactive. The argument can be made that there is some level of signal processing to differentiate a clap from background noise, and I won’t claim to be an expert on the matter, but I believe that it is still simpler than the thinking that Crawford calls for. This definition also excludes things like “interactive fiction”, because no thinking goes on in deciding between pre-coded paths in an interactive novel, and the reader doesn’t have free reign over the responses they can communicate to the characters of the story.

In this regard, I found that looking through the lens of degrees of interactivity makes more sense. Thus, things like refrigerator doors are low on the interactivity scale. Smart lamps, as well as many beginner Interactive Art projects, could be classified as medium interactive. Medium-high interactivity might include video games. And the highest tiers of interactivity are relegated to AI LLM chatbots and actual people. Thus, interactivity is a spectrum, and much to Crawford’s dislike, is inherently subjective.

Week 3 Reading Reflection | Aadil

In this reading, Chris Crawford presents interesting insights into what interactivity exactly means. I personally had not thought much about this, but this reading gave me a different perspective of looking at things. The idea of interactivity being qualitatively different from reactivity was interesting to me. It seems that there are certain things that are very hard to make interactive if they are kept as it is (such as a book).

The idea of how an interactivity designer is different from a user interface designer was also new to me. I really liked the analogy of form v/s function and how an interactivity designer focus on all three aspects of interactivity (listening, thinking and speaking). He also writes about graphic designing as being merely a subset of interactive designing.

I had never considered the challenges that interactivity designers would face in an industry where this is still an emerging field and, in a context, where interactivity designers are generally younger and less technically proficient.

Overall, this reading gave me a better understanding of what interactivity is and why it is important. The example that the author gave of a teacher being better than a mere book because of interactivity was very useful and helped me realize its importance. I hope to incorporate this way of thinking in designing future projects.

Assignment 3- Interactive Grid

For this assignment, I wanted to create a geometric and interactive artwork using OOP and functions. I was inspired by this youtube video: https://www.youtube.com/watch?v=4lCD9B4Dlik

My idea was to have a grid of spinning dial controls. Each dial displays a different hue pulled from the colour spectrum and it gives the final piece an ombre effect. As you move your mouse across the grid, the dials swivel to follow along. It creates this really cool hypnotic effect!

I created a Dial class to represent each control. In the setup(), I iterate through a 2D array to place Dial instances in rows and columns. I calculated the number of rows and columns based on the canvas size to fully fill up the space.

Each Dial is coloured according to its position in the grid using HSB colour mode. This lets me pull nice saturated tones from around the colour wheel. I mapped the grid indices to hue, saturation and brightness values. This creates a smooth gradient of colours.

for (let i = 0; i < cols; i++) {
  for (let j = 0; j < rows; j++) {
    // Map the grid position to HSB color values
    let hue = map(i + j, 0, cols + rows, 0, 360);
    let saturation = map(i, 50, cols, 100, 100);
    let brightness = map(j, 50, rows, 100, 100);

    // Set the fill color based on mapped HSB values
    fill(hue, saturation, brightness);

    // Call the rotateDial method of the  Dial instance with the current mouse position
    dials[i][j].rotateDial(mouseX, mouseY);

In draw(), all that’s left is to animate the Dials. This simply involves calling each Dial’s rotateDial() method, passing in the mouse position. Some tweaking was needed to get the rotation speed and smoothness right.

While the core concept is simple – a grid of colourful spinning things – the end result is quite striking and mesmerising. As the mouse moves, these colourful triangles swirl around the grid in different patterns. The black background makes it stand out and I’m pleased with how well it turned out.
I’m considering ways to expand on the idea in the future, maybe adding interactivity to control the colour mapping or rotation speed. I’m open to suggestions for other fun tweaks!

 

Reading Reflection: Week 3

The way the author defined the term “interactivity” caught my attention. To me, interactivity simply means interactions between two things or people. However, the author defined it in terms of a conversation where two actors actively take turn listening, thinking, and speaking. To further the definition, the author mentioned the role of subtasks (thinking, listening, speaking) in determining the quality of the interaction. Interactivity is not only about the interaction itself but also the subtasks that need to be well-performed to result in a high-quality interaction.

The author made an argument on what things are considered not interactive. I found myself agreeing with what the author defined as not interactive and an example given was a printed book. Although it speaks the words to the readers, it does not listen or think. In other words, the book and the reader do not alternately listen, speak, and think. In this way, the book is not interactive and hence cannot collaborate with humans, who are considered interactive.

To add on, an example of dancing as a non-interactive activity was a surprise. I thought dancing was interactive because dancers move according to the music. However, according to the author, dancing is not interactive because music is not an actor that can think and listen. It speaks the melodies and lyrics of the song but is not able to interchange with the dancer. Similarly, the movie is another subject that humans cannot interact with. Although I felt like I was exchanging ideas with the movies I watched, in fact, I was not interacting with the movies or the actors displayed in the movies.

Overall, the author’s definition of interactivity was fascinating. The author’s definition made me rethink what I consider interactive and hence how to develop good designs. While great designs can result between interactive and non-interactive actors, harmony between two interactive actors can also create designs of high quality and interest. With this reading, I will be trying to create designs that show the conversation of several interactive actors.

Assignment 3: OOP

The product of this assignment is an extension of assignment 2: I wanted to further develop the code for bouncing ball by using class. The concept of this work is shooting star. Recently, the weather in Abu Dhabi has been so nice and I have been enjoying taking “sky-gaze”. Looking at the night sky and the stars, I thought I could use class to create several stars on P5.

This is the class named Star. Under this class, there is a constructor that determines the position and speed of the star. Also, there are three other instructions that guide the actions of the star (move, bounce, and show). I didn’t encounter any difficulty while constructing class and this process was easier than constructing the code under function draw.

class Star {
  constructor(x,y,xspeed,yspeed) {
    this.x = x;
    this.y = y;
    this.xspeed = xspeed;
    this.yspeed = yspeed;
  }

  move() {
    this.x = this.x + this.xspeed;
    this.y = this.y + this.yspeed;
  }

  bounce() {
    if (this.x > width || this.x < 0) {
      this.xspeed = this.xspeed * -1;
    }

    if (this.y > height || this.y < 0) {
      this.yspeed = this.yspeed * -1;
    }
  }

  show() {
    noStroke();
    fill('rgb(241,241,214)');
    ellipse(this.x, this.y, 15, 15);
  }
}

This is the section of code that I struggled with. Because I wasn’t familiar with some of the code such as interactive, new,  and push, I had to spend extra time to figure out how to use the code. However, once I grasped an understanding of the code by referencing class slide, I could use it to draw interactive stars.

function mousePressed(){
  
  //adding new star
  let interactiveStar = new Star(mouseX, mouseY, random(-5,5), random(-5,5));
  star.push(interactiveStar);

}

This is a portion of code that I am proud of. I learned how to animate objects in P5 using arrow keys by watching this video. The overall process of creating this code was easy but I had to go back and make global variables to be able to animate the object (rocket).

  //moving the rocket up and down
  if (keyIsPressed){
    if (keyCode == UP_ARROW){
      b--;
    } else if (keyCode == DOWN_ARROW){
      b++;
    }
  }
  
  //moving the rocket right and left
  if (keyIsPressed){
    if (keyCode == LEFT_ARROW){
      a--;
    } else if (keyCode == RIGHT_ARROW){
      a++;
    }
}

For improvement, I would like to actually create a star shaped shooting star and not use an ellipse. In this way, a shooting star would be more well-represented.

Luke Nguyen – Week 3 Reading

I resonate with the interaction that the author proposes. Interaction is a “cyclic process” in which two actors alternately listen, think, and speak; it’s a back-and-forth listening, thinking, and speaking process indeed. The key is more than one, irrefutably. But I entertain his idea that we should think of interactivity as a “variable with relative measures.” Sometimes, defining whether an object as either interactive or non-interactive seems reductive and regressive. Things are more than what they seem and they certainly belong in the grey area of interactivity definition. Aiming to discuss the degree of interactivity seems to be a legitimate approach.

The author thinks that movies are non-interactive. However, in today’s context, this is not true entirely anymore, given the rise of interactive content on streaming platforms such as Netflix, with shows or movies like Carmen Sandiego: To Steal Of Not To Steal, Black Mirror Bandersnatch, etc.. Sure, the end result is pretty much very pre-determined, these programs are scripted anyway, but the concept and operation of the interactivity is successfully implemented. Pretty soon in the future, there will be interactive movie made for VR glass devices such as the newly released Apple Vision Pro.

I also find the idea about the contention between user interface and interactivity design to be fascinating. User interface from what I understand is all about front-end and the interactivity design back-end. But I’ve never thought about the tense relation between the interactivity designers and the user interface designers who detest the intrusion of interactivity designers into their work. I’ve always thought that each of these two aspects cannot exist without the other!

Luke Nguyen – Assignment 3 – Rainbow Spikes

This generative artwork is essentially me implementing the concepts of arrays and class that we learned. I was thinking of creating something fun and colorful and demonstrate a chaotic pattern that can be generated when a user press the mouse. And while scrolling through Openprocessing.org to look for inspirations, I stumbled upon a generative artwork called “Noise Turbulence Doodles” by Raven Kwok (https://openprocessing.org/sketch/143842).

The idea is that a circle generated from a mouse click is followed by a chain of automatically generated circles decreasing in size that scatter in random directions. I set the color spectrum for the circles to be a rainbow spectrum (referencing this p5js example by aferriss: https://editor.p5js.org/aferriss/sketches/Bys1YDQx7), with the root circle taking a random color every time the mouse is pressed or held. The longer the mouse is pressed at one position on the canvas, the more rainbow “spikes” are generated starting from the root. If the user moves the cursor around, they will scatter the root while creating the spikes as well.

The artwork generated looks like sea urchins or something spiky in 3D. This illusion is created by randomizing the distance between each circle that are generated in the chain from the root.

Using class and array:

let particle = new Particles(
      mouseX,
      mouseY,
      30,
      random(-5, 5),
      random(-5, 5)
    );
    //     add each circle generated after the root circle to the array
    circlelst.push(particle);

Creating a move class:

move() {
    //     the x-coordinate the circles increase according to the x-direction
    this.posX += this.directionX;
    //     the y-coordinate the circles increase according to the y-direction
    this.posY += this.directionY;
    //     the radius of the circles decrease by a random float from 0 to 1
    this.radius -= random(0, 1);
    //     draw the chain of circles
    if (this.radius > 0) {
      circle(this.posX, this.posY, this.radius);
    }
  }

Embedded sketch (Please press the mouse (either short press or long press) and move the cursor around to play with the effects):

This is very fun to make. The hardest part is to figure out how to generate the chain of circles that decrease in size as they are generated and how to trigger the circles to move in random direction consisting of x-direction and y-direction. It essentially required me to figure out how to work with arrays.

As for future work or improvements, I want to make the circles blend with one another smoothly to create a shape instead of separate circles. That way it can look even more hallucinatory.