[Assignment 3] Particle Simulator

Concept

For this assignment, I have created a particle simulator, in which small particles move away from the cursor and return to their initial positions. As the particles are in motion, their color will change. Recently, I have read several papers regarding electromagnetic forces and quantum fields. This project is inspired by the electromagnetic interactions between charged particles. I pictured small localized particles on a field, on which the particles are repelled by an external force (the cursor). The particles will then return to their initial position because they are most stable on those points. The color red means the particles are stable; the color blue means the particles are unstable.

Code

I began writing codes for declaring a class for small particles. Each particle will store 5 different pieces of information about their X and Y coordinates of their initial positions, X and Y coordinates of their current positions, and the color that will be used to set the stroke color.

class spacePoints {  //Declare class
  constructor(posX, posY) {
    this.posX0 = posX;  //Original X coordinate of the point
    this.posY0 = posY;  //Original Y coordinate of the point
    this.posX = posX;   //Current X coordinate
    this.posY = posY;   //Current Y coordinate
    this.color = 255;   //Color of the point when drawn
  }

The most challenging codes to write in this project was a class method, which updates the position of the particles depending on the cursor position. Using dist(), I measured distance between a particle and the cursor. If the distance is smaller than the defined threshold, the particle must be repelled. To do this, a vector that is always directed away from the cursor was declared. Then, the magnitude of the vector was modified to make its magnitude increase as the cursor gets closer to a particle. Since the particle is in motion, and thus, unstable, the particle’s color property is also modified.

If there is no cursor near a particle, a particle is moved back to its initial position. Another vector that points towards a particle’s initial position was created. Based on this vector, a particle’s position is updated.

movePoint() {  
    let cursorDist = dist(this.posX, this.posY, mouseX, mouseY); 
    if (cursorDist < 100) { 
        let dVec = createVector(this.posX - mouseX, this.posY-mouseY); 
        dVec = dVec.setMag(100 / dVec.mag()); 
        this.posX += constrain(dVec.x, -20, 20); 
        this.posY += constrain(dVec.y, -20, 20); 
        this.color = 0; 
    } else { 
        if (abs(this.posX - this.posX0) > 1 || abs(this.posY !=       this.posY0) > 1) { 
        let dVec = createVector(this.posX0 - this.posX, this.posY0 -    this.posY);
        dVec.setMag(1);
        this.posX += dVec.x; 
        this.posY += dVec.y;
      }else this.color=255; 
    }
  }

In the end, I wrote a short method that draws a particle based on the canvas. One noticeable thing is that the stroke color will change depending on a particle’s color property.

 drawPoint() {  //Draw a spacePoint
    noFill();
    stroke(this.color,125,125);
    strokeWeight(3);
    circle(this.posX, this.posY, 8);
  }

Click listener is also used, so the user can freely add particles on specific points they click on.

function mouseClicked() {  //When mouse is clicked
  append(pArr, new spacePoints(mouseX+random(-5,5), mouseY+random(5,-5)));  //Generate new spacePoint at where the mouse is clicked. Store it in pArr[]
  pNum++;  //Increase number of current number of spacePoints by 1
}

The draw function is rather very simple because all calculations are done by the functions and objects.

function draw() {
  background(0);

  for (let i = 0; i < pNum; i++) { 
    pArr[i].movePoint();  //Update positions of spacePoints in pArr
    pArr[i].drawPoint();  //Draw spacePoints in pArr on the canvas
  }
}

Reflection / Future Improvements

I am very happy about my project’s complex mathematical logic behind the simple appearance. I initially added lines that show the current direction and velocity of the particle’s motion, but I had to remove the lines to keep my project look simple. This is the first project that I did not use translate()  to handle coordinate calculations, which I found surprisingly easy without shifting my origin to the canvas center.

If I have another opportunity to work on this project, I would like to change and improve upon these:

  1. Optimization. Though code seems to run smoothly regardless of the number of particles, there are rare moments the code takes time to start. I believe this problem occurred because I used vectors for angle calculations. Instead of calculating angles via vectors, the program may run faster if mathematical expressions are used.
  2. Collision Detection. The project will look more interesting if each particle interacted with the other. If each particle has collision detection features, the particle simulator will be more realistic. However, because collision detection require more computing power, the codes must be optimized before adding this feature.

 

Assignment 3: OOP Generative Art

This assignment seemed similar to the previous one except how I approached the problem. The goal is to generate art Through Object Oriented Programming (OOP). After seeing an art in Eyeo2012 – Casey Reas video, I wanted to create something similar to the the below image:

9:17

Small, individual creature-like objects moving around black dots. This looked interesting to work on. So, initially, I thought about placing food, creatures, and their predators. But while simulating how my code will work, I realized that it will require a lot of resources(avoiding collisions, having a proper line of sight, etc.) to populate even hundreds of creatures. So, instead of having creature-like objects, I decided to make something simpler: objects that follow gravity.

The above is done as a class work. However, it does not seem like a generative art because it looks too vacant. Also, I do not want the center of gravity to shoot away objects. So I worked on details.

Better. There are 2 major changes other than fancy colors. First, there are tails to the moving objects. As objects move, they leave traces of their previous positions. This is done by a simple trick: instead of overwriting the board with a solid color, use a color with high transparency. The below is the code.

background('rgba(0,0,0, 0.08)');

Second, when particles move too close to the center (and therefore are at risk of being launched back in high velocity), they become reinitialized through init() function. The function is basically a constructor but has a callable name. The below shows how it is done.

constructor() {
  this.init();
}

init() {
  this.size = random(2,8); // random size
  this.vx = random(-3,3); // initial x velocity
  this.vy = random(-3,3); // initial y velocity
  this.x=this.size/2 + random(width-this.size); // initial x position
  this.y=this.size/2 + random(height-this.size); // initial y position
  this.px=this.x;
  this.py=this.y; // previous x and y (for smoothing shapes)
}

...
if (d<30) {this.init();}
...

While working on the above code, I worked on another branch of the project in parallel. Its features include mouse position being the center of gravity and changing the direction of gravity (positive and negative gravity). The sketch is created for the purpose of practice (thus labeled “PR”), so the code is a bit messy and commented not-so-greatly.

Wait… This reminds me of a firework… 

Inspired by what was seen in the above sketch, I created a firework as a side project (“PR”actice). In a big picture, it operates the same way as the gravity function. A circle (point of negative gravity) moves toward the center, and when it reaches its maximum height, 500 colorful circles get teleported around the circle and get pushed away. For more realistic visuals, particles follow gravity toward the floor and their size become smaller as they “burn” over time.

I know. There are too many sketches in one post. I promise to finish my post with one last thing, the generative art. Now that I think of it, it has much less code and complexity compared to the firework, but it does what it needs to do. It should be alright. It is very similar to the second sketch, with slight modifications such as smaller particles and having no velocity other than toward the center.

The biggest problem I encountered during this project was not the difficulties in coding, but headaches I got from my own artwork. Before realizing it was a terrible idea (I just realized as I write this post), I made my generative artwork colorful, which looked like the below.

Click the canvas to see colored version.

Imagine seeing thousands of these colorful moving dots and fine-tuning parameters and functions for hours. Definitely a terrible idea. Now I learned that more color does not mean a better art. It was a costly lesson. I hope other people to not make the same mistake as I did this time.

 

 

Assignment #2 – Disco Disc

Concept:

I didn’t have a clear image of what I wanted to produce when I first created the canvas, but I knew I wanted to incorporate the skill of randomly switching from one color to another. At the very beginning, I wanted to devise many small circles with switching colors, but after having problems duplicating the circles, I decided to just focus on creating one giant one, which inspired me to create a disc with flashing colors, like a disco-themed disc. I also added some repeating white circle outlines within the giant disc, so that it will create an effect of a record disc.

* duplicating many circles like this one to fill the entire screen was my original vision.

Process/Coding:

First, I created my background, which I made into a dark navy color. I wanted the background to be dark so that it will help the flashing colors pop out more, but I also didn’t want it to be completely black because that was too basic! As for creating the main “disc” as well as its details such as the switching colors, white outline strokes, etc., I consulted a YouTube video called “4.1: while and for Loops – p5.js tutorial” from a channel called “The Coding Train.” From this video, I was able to learn new skills such as how to use the “strokeWeight()” (which controls the thickness of a stroke) and “stroke()” (which controls the color of a stroke) function, which I used to outline my disc circle and to create smaller circles within it. This was a huge highlight of this project, and here’s the coding that I used for creating the white stroke around the entire disc:

// thick white stroke around the "disc"
function draw() {
  strokeWeight(7);
  stroke(255);

(original author of the code: Daniel Shiffman, link to the code: https://thecodingtrain.com/tracks/code-programming-with-p5-js/code/4-loops/1-while-for)

Here’s the gradual progress from the original one big circle to adding more white circle outlines within the disc:

As for the loop, which was the main technique that we had to use for this project, I set xPos, yPos, height, and width, and used “for” to create a condition in which the loop will continue to run. Because I was still unsure about how to create loops, I got help from Professor Shiloh’s example from the lecture notes. Here’s the code that I used to create the loop:

//loop
for (yPos = 300; yPos < height; yPos = yPos) {
  for (xPos = 300; xPos < width; xPos = xPos) {
}
}

(original author of the code: Professor Michael Shiloh, link to the code: https://github.com/michaelshiloh/IntroductionToInteractiveMedia/blob/master/lectureNotes.md)

Final Product:

It took a while to figure out how to switch colors in order to create the “flashing” effect, as well as layering the white circle outlines so that none of them overlap but decrease slowly in size, but eventually I was able to finalize my disco disc:

Reflection:

This project has taken significantly less time than my first one, although the skills that I’ve used were less “basic” and a little bit more “intricate,” which I found interesting. I’ve had a blast with this one because I’m slowly grasping the language of coding, and it’s so awesome to be able to conquer one skill at a time and use them to produce something that I’ve visualized in my head. I’m extremely happy with the switching of colors, and if I try something like this again next time, I’d like to figure out how to make the entire disc move around, because I still haven’t really figured out how to make mobile projects!

(a very rushed) self-portrait!

Concept:

To be frank, I didn’t have the luxury to be creative with my self-portrait because I was running dangerously low on time; actually, creating a mini version of me with my (very) limited knowledge of coding seemed almost impossible.
So in hopes of keeping the assignment as simple as possible, I focused on the main central characteristics of myself: the colors of my hair, skin, eyes, etc., my general build, and my most common facial expression. Although I initially hoped to focus on the details of my face specifically, I quickly realized the limits of my current coding experience, which mdae my drawing very basic.

Process/Coding:

Thankfully, I was able to gather bits of coding techniques from Professor Shiloh’s lecture notes, specifically on shapes, colors, and the background. Some struggles that I’ve faced during this project were: 1) figuring out the RGB color codes manually until I realized that I can use a tool called “color picker” to generate the codes without having to try out a bunch of different ones, 2) positioning the shapes in the desired spots, which also took a lot of trials and tribulations, and 3) creating arcs, which was honestly the hardest part of this project. Because the arc was the most challenging for me, it’s also the part of my project that I’m most proud of.
Here’s the code that I used for it:

fill(252, 28, 3);
arc(x, y, 70, 100, radians(30), radians(150), CHORD);

Despite the numerous complications (and the frustrated growls I’ve made while creating this), I did have some small wins as well, such as being able to master features such as “fill” and “function draw,” as well as learning how to create the general shapes such as a rectangle, ellipse, etc.

Here is my final product:

Reflection:
There are so many new skills that I want to try out for my upcoming projects that I didn’t quite have the time (and energy) to master yet. Although this one wasn’t exactly a satisfying end product, I’m compromising with myself by believing that given time, I’ll be able to come around to the world of coding and unlock all the cool, fun techniques that I can use to express my creativity! I’d like to make a non-stationary product next time, because I’d like to experiment with coding that generates movements, etc. But for now, I’m glad with this quirky little character that I’ve made. 🙂

instrumentalist with a hat

concept:

This week’s assignment required us to explore the shapes offered in the p5 coding program and make a self-portrait. The first thing I did was to draw a huge circle right in the middle of the canvas, and that was when I saw it… my face. I planned to draw a minimalistic cartoonish face that represents my hobby, playing the ukulele, and myself with a certain clothing item of some sort.

code:

function setup() {
  createCanvas(650, 450);
  
    //assign variables
  let midX = width/2;
  let midY = height/2;
    
    //blue background circles
  background(50, 80, 120);
  strokeWeight(0);
  fill(80, 115, 150);
  circle(midX, midY, 690);
  fill(105, 140, 180);
  circle(midX, midY, 590);
  fill(190, 210, 230);
  circle(midX, midY, 480);
    
    //head
  fill(230, 170, 140);
  strokeWeight(3);
  ellipse(midX, midY, 365, 390);

    //eyes
  fill(230);
  circle(midX -100, midY +45, 100);
  circle (midX +100, midY +45, 100);

    //iris
  fill(100, 55, 15);
  //stroke(80, 35, 0);
  ellipse(midX -95, midY +44, 80, 80);
  ellipse(midX +95, midY +44, 80, 80);

    //pupils
  fill(0);
  circle(midX -93, midY +44, 45);
  circle (midX +93, midY +44, 45);

    //glare
  noStroke();
  fill(235);
  circle(midX -75, midY +40, 20);
  circle (midX +125, midY +40, 20);
  
    //smile
  stroke(0);
  noFill();
  arc(midX, midY + 90, 50, 30, radians(0), radians(140));
  
    //hat
  fill(220);
  ellipse(midX - 180, midY - 65, 120, 90);
  fill(233);
  arc(midX, midY - 20, 365, 350, PI, TWO_PI, CHORD);
  
    //hat details
  fill(230, 170, 140);
  arc(midX, midY - 35, 90, 80, PI, TWO_PI, CHORD);
  line(midX, midY -195, midX, midY - 75);
  noFill();
  arc(midX, midY - 20, 280, 350, radians(270), radians(0));
  arc(midX, midY - 20, 280, 350, radians(180), radians(270));
  noFill();
  fill(200);
  rect(midX + 20, midY - 40, 15, 24, 5);
  
    //eyebrows
  stroke(0);
  strokeWeight(5);
  noFill();
  arc(midX -90, midY + 5, 115, 40, radians(190), radians(290));
  arc(midX +100, midY + 8, 110, 40, radians(220), radians(320));
  
    //instrument
  strokeWeight(3);
    //ukulele neck
  fill(60);
  rect(midX +232, midY -80, 35, 255);
  fill(180);
  rect(midX +232, midY -90, 35, 10);
    //ukulele frets
  fill(180);
  rect(midX +232, midY - 70, 35, 6);
  rect(midX +232, midY - 55, 35, 6);
  rect(midX +232, midY - 40, 35, 6);
  rect(midX +232, midY - 25, 35, 6);
  rect(midX +232, midY - 10, 35, 6);
  rect(midX +232, midY + 5, 35, 6);
  rect(midX +232, midY + 20, 35, 6);
    //ukulele head
  fill(150, 80, 40);
  rect(midX +229, midY -137, 40, 50);
  fill(200);
  circle(midX +238, midY -120, 8);
  circle(midX +260, midY -120, 8);
  circle(midX +240, midY -100, 8);
  circle(midX +256, midY -100, 8);
    //ukulele body
  fill(150, 80, 40);
  ellipse(midX +250, midY +130, 120, 100);
  ellipse(midX +250, midY +80, 105, 100);
  fill(35);
  circle(midX +250, midY +90, 45);
  fill(35);
  rect(midX +230, midY +142, 40, 12);
  stroke(150, 80, 40);
  strokeWeight(5);
  noFill();
  arc(midX +250, midY +80, 105, 100, radians(27), radians(153))
    //ukulele strings
  fill(235);
  stroke(0);
  strokeWeight(2);
  rect(midX +236.5, midY -117, 1, 270);
  rect(midX +259.5, midY -117, 1, 270);
  rect(midX +244.5, midY -100, 1, 253);
  rect(midX +251.5, midY -100, 1, 253);

}

function draw() {
  //print(mouseX, mouseY);
}

 

method:

Initially, I started the sketch by limiting myself to solely using the ‘circle’ and ‘ellipse’ functions. I successfully managed to fill that huge circle with glaring brown eyes, eyebrows, and a mouth. Then came the clothing aspect of the sketch. I wanted something that represented me, and the first item that came to mind was the hat I occasionally wear to class. This was somewhat challenging given that the hat is completely constructed using the ‘arc’ function. It was an extremely challenging yet rewarding addition to the sketch as I could add little details such as a metal strap using the ‘rect’ function. Finally, n instrumentalist would not be one without an instrument. Thus I added the ukulele, a combination of circles, rectangles, lines, and arcs.

sketch:

The following images preview how the portrait sketch came to life to become what it is!

future improvements:

Adding some sort of movement to the program that provides an animation aspect would be amusing. For instance, making the eyes move to look wherever the mouse is, or possibly even making the ukulele a playable instrument!

iconic scribbles

concept:

As soon as I was informed about the assignment being an art presentation, world-known art pieces immediately came to mind. Whether it’s the beautiful Mona Lisa, the alluring Great Wave of Kanagawa, or the charming Starry Nights, I knew that using such iconic art pieces would be my inspiration for this assignment. However, I did not want to approach it from an ordinary/cliche perspective. Instead, I intended to present art in its most crucial form… when it’s nothing lines, shapes, and scribbles during a quick sketch. This drawing stage is what shows the artist what path this art piece will eventually take. That being said, how would you imagine those incredible art pieces mentioned earlier in a form where it is composed of nothing but lines and shapes? How thick would the lines be? What shapes would be used? How far will the spacing between the shapes and lines be? Answering and exploring these questions will display the concept I have in mind.

code:

//indicate variables
let img;
let canvas;

//load image
function preload() {
  img = loadImage("assets/5.jpeg");
}

function setup() {
  //create canvas with image dimensions
  canvas = createCanvas(img.width, img.height);

  //update canvas
  let updatedCanvasX = (windowWidth - img.width) / 2;
  let updatedCanvasY = (windowHeight - img.height) / 2;
  canvas.position(updatedCanvasX, updatedCanvasY);

  //draw until canavs edge and set difference between curves
  for (let column = 0; column < img.width; column += 2) {
    for (let row = 0; row < img.height; row += 2) {
      let x = column;
      let y = row;

      //get image attributes
      let m = img.get(x, y);

      //strokes attributes
      push();
      translate(x, y);
      rotate(radians(random(360)));
      noFill();
      strokeWeight(random(1));
      stroke(color(m));

      //add random circles representing splash
      push();
      strokeWeight(random(3));
      point(x, y);
      pop();

      //draw curved lines
      curve(
        x,
        y,
        sin(x) * random(5),
        cos(x) * sin(x) * random(50),
        random(30),
        random(50),
        cos(y) * sin(y) * random(10),
        cos(x) * sin(x) * 20
      );
      pop();
    }
  }
}

 

method:

Starting off, to work with already-existing art pieces that I would have to import into my program, I initially had to research how images work in JavaSript. Understanding how a loaded image’s dimensions can work and be modified with a program’s attributes allowed me to link my image’s colors to the shape I would eventually choose. I started exploring numerous shapes to see what would be ideal for a ‘scribble’ theme and found the ‘curve’ ideal to my vision. After confirming the shapes used in the program, I started experimenting with the thickness, length, and spacing of the curves. Also, adding small circles of different sizes was revealed to be a convenient way to represent some form of splatter on the canvas. That being said, these experiments resulted in a vast range of incredible yet unique sketches.

sketch:

The following images are different runs on the program used on the NYUAD Logo where the ‘curve’ line attributes were modified:

 

^ stroke weight: 1 – 6 ; rotation: 360 ; circle radius: 1 – 4 ; spacing = 5

 

stroke weight: 1 – 4 ; rotation: 180 ; circle radius: 1 – 10 ; spacing = 12

 

stroke weight: 1 ; rotation: 120 ; circle radius: 1 – 2 ; spacing = 2

 

future improvements:

I initially had several ambitious plans that I, unfortunately, could not complete due to my limited knowledge of JavaScript. All of these ideas would have added a form of user interaction that would be great to have in such a program. First, allowing the user to change the image by pressing the keys ‘1’ through ‘5’, all of which display a different iconic art piece. The second would be a ‘save’ button allowing the user to save one’s own art piece, given that each run displays a completely new, never-seen-before illustration! Last but definitely not least would have been a functionality allowing the user to possibly upload their own picture/art piece and see how it would be if it were a ‘scribble!’

game:

Guess the following art pieces from the displayed program edited image: (answers below)

 

 

 

 

  1. The Great Wave of Kanagawa
  2. Starry Nights
  3. The Scream
  4. Mona Lisa

 

Assignment 2: Art with Loops

Concept

For this assignment, I wanted to a create a simple piece of art with the emphasis of my understanding of it. Last time I got ahead of myself and was trying to do so much that I ended up doing very little. For inspiration I used a traffic light for no particular reason. It’s simple and I knew I at least had to use ellipse() and rect() if I wanted. I also knew I had to work with the colors black,  green, red, and yellow. I looked up images for inspiration and found photographs of traffic lights with long exposure and decided to do a very simplified version. Below is the image I used for inspiration.

Moody Traffic Lights: How To Make Something Beautiful From Nothing

Initially, I was very confused with how loops worked. I watched a lot of YouTube videos, mainly from The Coding Train, and after I grasped the concept, I started building my for loop first. I copied the loop two more times to represent the three lights in the traffic light. I also used the createColorPicker() DOM from the p5.js reference page to randomize the colors and added a frame rate to try and visualize the exposure aspect.

for (let ellipseX = 20; ellipseX < 400; ellipseX += 25) {
   ellipse(ellipseX, 200, 70)

 

Future Improvements

I was satisfied with my understanding of the assignment, loops, and the overall art piece. However, for next time I would like to experiment and include more of what we have learned from previous lessons and create my own functions.

 

 

 

 

 

 

 

 

 

The Village

For this project, we were meant to experiment with using for and while loops.
I really liked the dots that the professor created in class using nested for loops

So I experimented with using for loops to layer shapes with different colors under the dots.


This reminded me of lego pieces, but I though it might be interesting for the colors of the shapes to be different based on their position on the canvas. I decided to change the shapes to mountains (triangles) and let shapes at the back to be lighter and the ones at the front to be darker to add depth.
mo

The triangles overlapped each other in a way that I didn’t intend, so I decided to add a rectangle that stretched till the end of the page under them to mimic the ground so it would look more like a landscape.
This took a bit of time since I wasn’t sure which values would align the rectangles to the bottom of the triangle.


This is how it looked once I got that step done:


At this point, they didn’t look like how I wanted the mountains to look like but I felt like they might look more like houses. So I changed the color of the base and decided that they do look better as houses so I continued with that.

I changed the colors of the bases again to a color that matched the housetops and then decided to also let the color of the bases change based on their position.
I also started experimenting with the repeating dots and the numbers in the 4 loop and realized that adding a value that continuously increments to the x and y position skewed them creating a diagonal line of circles that is shorted at some parts and longer at others. I made the dots really small and that resulted in rain like lines.

  fill("#ddd7ff")
  stroke("#ddd7ff")

  for (let row = 10; row < 400; row+= 20)
    {
    for (let col = 10; col < 400; col+= 20)
      {
      ellipse(row+b, col+b, 0, 0);
      }
      b++;
    }


This is the final result:


link: p5js project

challenges and improvements:

I think it would’ve been interesting to add rain that continuously poured but I didn’t manage to figure out how to do that. I think would also be interesting to experiment with different colors, where if the person generated a village at night the colors would be darker vs if generated in the morning they would be lighter. Maybe there is a get time function that I could use for that.
I’d also like to experiment with creating patterns using lines, I think that this might be interesting.

Art piece

Concept:

A single line, judiciously placed around the main features, might suggest several moods. With this artwork, I wanted to display a variety of colours and lines that, when combined, display a range of emotions. Horizontal lines frequently convey a sense of stability, peace, and tranquility when utilized in conjunction with other shapes. The word “horizontal” comes from the word “horizon,” which is another symbol for perspective, separation, and tranquility. The possibility for mobility is strongly shown by vertical lines. When constructing perspective drawings and scenarios, vertical lines are frequently utilized in conjunction with horizontal lines as lines of reference.

Reflections and improvements:

Making this was enjoyable and relatively easy. But I wish there had been some kind of interactive component. Something that might change colours dependent on mouse movement. After this design was finished, I tried adding more visuals, but I ran into some problems. That is something that I would want to include in this sketch.

Assignment 2: Loop-Based Digital Art

Concept

It took a little thought, but an image that soon sprung to mind for me was the pattern of multicolored rectangles that you see when a TV channel is off-air, the one that is accompanied by that awfully grating (and sometimes eerie) high-pitched beep. The one that looks like:

This pattern is called the SMPTE color bars (SMPTE stands for the Society of Motion Picture and Television Engineers). Image courtesy of its Wikipedia article: https://en.wikipedia.org/wiki/SMPTE_color_bars

I thought this would serve as good inspiration for my own artwork of patterns. After getting just a little invested in trivia (Did you know that that continuous beep is usually a 1000 Hz sine wave?), I set off to work.

Coding Highlights

I first sought to recreate the pattern. After a little tinkering, I was able to write up a function that would draw the pattern across the canvas when repeated.

//Set Variables
let x = 0;
let x2 = 0;
let i = 0;

//Function for Generating One Color Bar of Each Row
function colorBars(){
  noStroke();
  fill(random(255), random(255), random(255));
  rect(x, 0, 63, 220);
  fill(random(255), random(255), random(255));
  rect(x, 220, 63, 30);
  x = x + 63;
  fill(random(255));
  rect(x2, 250, 73.5, 80);
  x2 = x2 + 73.5;
}

This function is then embedded within a simple while() loop, which runs just enough times to make the pattern fill the canvas.

//Repeat for Pattern
function draw() {
  while (i < 7) {
    colorBars();
    i += 1;
  }

The x = x + 63; and x2 = x2 + 73.5; lines of code in the colorBars() function move the position of the future rectangles’ starting points to the end of the now-drawn rectangle, thus allowing for the pattern to be continued seamlessly when the function is repeated. I also chose to make the colors random (the bottom row is in grayscale for contrast and to match the feel of the reference image), which makes each iteration of my program unique. Here is the complete draft:

Draft in hand, I now wanted to add a layer of animation and make the bars change color (or more precisely, generate new bars over the preexisting ones). I also wanted to keep the animation from looking too stale by varying the cycle speeds of each row of bars—this meant that I had to break up the colorBars() function into three separate functions (one for each row) and establish separate variables for each function.

//Establish Variables

  let x1 = 0;
  let x2 = 0;
  let x3 = 0;
  let i1 = 0;
  let i2 = 0;
  let i3 = 0;

//Establish Functions for Each Row of Bars

function barTop(){
  noStroke();
  fill(random(255), random(255), random(255));
  rect(x1, 0, 63, 220);
  x1 = x1 + 63;
}

function barMid(){
  fill(random(255), random(255), random(255));
  rect(x2, 220, 63, 30);
  x2 = x2 + 63;
}


function barBot(){
  fill(random(255));
  rect(x3, 250, 73.5, 80);
  x3 = x3 + 73.5;
}

With the functions established, I could move on to the draw() function. First in line was the initial setup, which follows the same logic used for the while() loop in the draft (now with three functions looping within it).

//Initial Setup - This is in the draw() function.
while (i1 < 7) {
  barTop();
  barMid();
  barBot();
  i1 += 1;
  i2 += 1;
  i3 += 1;
}

The stage was set, and this was where the function separation came in handy. I was able to write three blocks of code that would determine the cycle speeds of each row, as well as reset their positions as needed:

//This is in the draw() function following the setup.
  //Top Bar Generation
  if (i1 % 5 == 0){
  barTop();
  }
  if (i1 % 35 == 0){
    x1= 0;
  }
  i1 += 1;
  
  //Middle Bar Generation
  if (i2 % 7 == 0){
    barMid();
  }
  if (i2 % 49 == 0){
    x2 = 0;
  }
  i2 += 1;
  
  //Bottom Bar Generation
  if (i3 % 6 == 0){    
    barBot();
  }
  if (i3 % 36 == 0){
    x3 = 0;
  }
  i3 += 1;

The i1, i2, and i3 here act as counters for the number of draw() loops the program has gone through—by pairing them with the % remainder operator, I was able to vary the speeds at which the new bars are drawn over the preexisting ones. The first if() function in each block controls the rate at which a new bar is generated, while the second if() function resets the position of generation back to the beginning when the new pattern has gone across the width of the canvas. And finally, the result:

Reflections

Overall, this assignment was a fun one to work on! I was especially satisfied with how I was able to separate the initial bar-drawing function into three and make them run at differing intervals using the loop counters and the remainder operator. Each feature I want to implement in a project is a puzzle of its own, and it feels rewarding when I successfully devise a solution (sometimes after much frustration).

One feature I would have liked to adjust is to have the bars scroll across the screen rather than (seemingly) just change color. This was the initial idea I had, but I soon realized that making all the bars move, especially with each row at different speeds, was a much more complicated task than I had imagined. A task for a different time, perhaps.

Exploring the capabilities of p5.js—and that of my own with the editor—has been an exciting journey thus far, and I look forward to what more may lie in store!