Week 3 – OOP artwork

Concept

The artwork initially depicts raindrops falling onto a dark background.  I thought of it as a depiction of when I am feeling down or having a bad day. However, I wanted the background to change color as the raindrops are clicked, as I wanted to depict how absorbing the beauty in the small things or interactions can reflect positively on my wellbeing and entirely change the vibe.

Implementation
// global variables 
let s;
let gShapeArray = [];
let numShapes = 10;
let howmanyCircles = 10;
let deletedCircles = 0;
let rr = 0;
let bb = 0;
let gg = 0;

//function for detecting the shape on mouse press
function mousePressed(){
  for(let i = 0; i < gShapeArray.length; i++){
    gShapeArray[i].clicked(mouseX,mouseY,i);
  }
}

//class for a Shape being dropped 
class Droped_shape{
  constructor() {
    this.x = random(width);
    this.y = 0;
    this.width = random(20, 50);
    this.speed = random(0.5,3);
    this.r = random(250);
    this.g = random(250);
    this.b = random(250);
  }
  //movement downwards
   move() {
    this.y += this.speed;
  }
  //how the shape is shown on screen
  display() {
    fill(this.r,this.g,this.b);
    stroke(255);
    strokeWeight(2);
    ellipse(this.x, this.y, this.width, this.width);
    this.move();
  }
  //what happens to shape when clicked 
  clicked(px,py,index){
    let d = dist(px,py,this.x,this.y);
    if(d < this.width){
      rr = this.r;
      bb = this.b;
      gg = this.g;
      //deleting object from array(destructor)
      gShapeArray.splice(index,1);
      numShapes--;
      
    }
    
  }
  
}
function setup() {
  createCanvas(400, 400);
 // creating an instance of dropped shape
  s = new Droped_shape();
  //creating initial instances of shapes
  for(let i = 0; i < numShapes; i++){
    gShapeArray[i] = new Droped_shape();
  }
}

function draw() {
  background(rr,gg,bb);
  smooth();
  s.display();
  for(let i = 0; i < numShapes; i++){
    gShapeArray[i].display();
    //delete circles exiting canvas from array
    if(gShapeArray[i].y > height){
      gShapeArray.splice(i,1);
      numShapes--;
      deletedCircles++;
    }
  }
  //controlling the rate and flow of dropped shape 
  let rand = int(random(0, 100));
  let rand2 = int(random(0, 100));
  //randomly creating shapes over time controlled with two if loops, could have used Perlin noise for this.
  if(rand % 5 == 0){
    if(rand2 % 3 == 0){
    //adding obects to arracy (could have been done with gShapeArray.push)
    gShapeArray[numShapes] = new Droped_shape();
    numShapes++;
      howmanyCircles++;
     }
  }
  //print to console to keep track of circles 
  console.log(howmanyCircles,deletedCircles);

}

Some interesting parts of the code were definitely the creating and and using the classes. I wanted the background to take the color of the object that has been clicked. The workaround for this was to assign the objects color (where random RGB values were given to 3 variables r, g and b) to a global variable later assigned to background when the mousePressed() function was called. This could have also been done as an array where the numbers were saved to an array and the values inside the array were later given to the background.

Also, I realized that the array just keeps on taking objects indefinitely, which significantly slowed the sketch later in run-time. The workaround for this was to delete the objects which had reached the bottom of the screen.

I had to revisit a lot of p5.js reference, sketches done during lectures and coding train videos to solidify the concepts of Object oriented Programming before I could implement a functioning class.

Sketch

Reflections

Looking back, I could have used more elegant features such as array.push(object) and Perlin noise to determine creating of objects. However, it was really cool to be able to finally give more meaning to my artwork than before. The animation still isn’t as smooth as I would like it to be, as there are very evident glitches, this maybe due to the inefficient memory use. I would have also like to implement a function to merge objects or detect collisions as this would have made the sketch look much more natural in a way that it shows the true behavior of water droplets.

 

 

Assignment 3 (GenArt)

Concept

This assignment required creating a generative artwork using Object-Oriented Programming, paying attention to the structure, clarity, and organization of the program. As usual, I started off the project with something very ambitious, a piece inspired by Manolo Gamboa Naon (Link to his art).

Code

A greater part of the code was inspired by the examples we had in class as well as the tutorials we were required to watch. While my final piece had nothing particularly interesting to represent in terms of code, I must admit the learning process was an interesting ride. I tried applying most of the concepts we learnt, and was pretty confident that they should have been enough to produce a similar piece to the one I was inspired with. However, there were quite some challenges, such as generating the vectors surrounding the circles,  during the process which required me to improvise and come up with the piece that I have.

for (let i = 0; i < 5; i++){
      fill(random(100,255), random(100,255), random(100,255));
      push();
      translate(this.x, this.y);
      rotate(TWO_PI * i / 5);
      ellipse(60, 0, 10, 10);
      pop();
    }

Reflection / Future Improvements

I am not quite sure how I feel about my piece. I spent a lot of time on it yet I could not reach the level of creativity I was envisioning. On the bright side I believe I have learnt a lot, and there is still more to learn along the way. Some things I would work on the piece is it being more detailed, sophisticated, perhaps even animated.

Loops

THE SKETCH 

For this project, I made two similar sketches: one that is dynamic, and one that is a still image.

I. The dynamic sketch:

The link to my code in the online editor for version 1 can be found  here. 

 

II. The still sketch:

The link to my code for the second version can be found here.

INSPIRATION & DESIGN: 

The idea for this project came to me rather slowly. Usually with any new artwork I have a very clear idea about what I want to create and can visualize it on paper before I start coding. However, I had a lot of difficulty because I personally don’t love artwork that heavily relies on randomness, and I don’t love overly abstract/geometric designs (conveniently what loops are good for!).  After hours of trying to come up with a uniform idea, I decided to just start coding. I knew that I wanted to challenge myself by working with noise(), and I enjoy working with sin() and cos() functions. I used these two things as my starting point.

In the end, I ended up creating a sort of wavy sun pattern that stretches and contracts with the help of the noise() function. I later wanted to have several of these patterns on the same canvas, but this was too much for my computer to handle and resulted in very slow and glitchy animation (likely due to the nested for loop and calling noise() with each iteration). Consequently, I created a second version of a sketch that does not animate and simply consists of 5 sun patterns randomly placed on the canvas. While I do wish this one also animated, I think it still looks beautiful.

 

CODING SPECIFICS

Each sun pattern is composed of of several sine waves that are rotated about an invisible center point. In the first version, that point is the center of the canvas; in the second version, 5 points were chosen at random.  The first version uses a simple for loop inside the draw() block, while I create a separate function called spirals() in the second version that is called 5 times within a for loop in draw(). To make the sketch s Regardless, the integrity of the algorithm for drawing these shapes is the same in both. A snippet of the code for function_squiggles() is shown below:

for (let j = 0; j < 16; j++) { 
beginShape();
  rotate(PI/8); 
  for (let i = -800; i < 800; i++) { 
    y= noise(xoff) * amp * sin(i/(period)); 
    vertex(i, y);
    
    xoff+=0.00001; 
  }
endShape();

 

The waves are drawn using a custom shape, which basically plots each point (vertex) on the sin wave and connects them together to create a uniform curve.  Each vertex has an x-coordinate that increments by 1 with each iteration. An upper bound  800 is used to ensure that even shapes whose center point is at the edge of the canvas can extend all the way to the edge. The y coordinate is dependent on the sin() function, who’s amplitude changes every frame based on the constant variable amp and the changing variable xoff. This variable begins at 0.0 and increments by 0.0001 with each iteration; as a result, each frame when the noise() function is called it returns a different number.

You may notice that some of the waves appear thicker than others and some lines appear to overlap. This was done by layering a second for loop in addition to the first one shown above . Continuing in the function_squiggles() we have:

for (let j = 0; j < 12; j++) { 
beginShape()
  rotate(PI/12); 
  for (let i = -800; i < 800; i++) { 
    y= noise(xoff) * amp * sin(i/(period));

    vertex(i, y);
    xoff+=0.00001; 

  }
endShape();

Note that the degree to which each wave is rotated is now PI/12 and iterates 12 times, in contrast to the first for loop, which has each wave rotating at PI/8 and iterates 16 times. This slight difference allowed for the shape to have some irregularity, and to look more “organic” versus geometric.

REFLECTIONS: 

While I feel that the actual code of this project was far easier than that of last weeks, I experienced much more difficulty creating the design for this one. Still, I’m not quite sure what I’ve created and how I feel about it; however I’ve stepped outside of my IMA comfort zone in that I created something without any pre-planning, and rather relied on experimenting and improvising. Being a lover of control, these are skills that I’ve always struggled with as an artist, but I am happy that I was able to have a different approach for this project.

 

Assignment 3: Object Oriented Generative Art

Inspiration

For this assignment, I have replicated the renowned particle physics experiment called ATLAS, the largest general-purpose particle physics experiment at the Large Hadron Collider (LHC) (at CERN in Switzerland). The scientists at LHC use the Higgs boson (an unstable particle that decays into stable particles) to search for dark photons. The image below (Image 1) is related to an experiment completed on May 18, 2012, where the ATLAS detector records a Higgs boson decay; the second image (Image 2) is also related to a similar experiment. Thus, in this project, I have created an animated simulation of the experiments mentioned above — it is an amalgamation of two images shown.

Image 1 – Higgs decay to four electrons recorded by ATLAS in 2012. Source: atlas.cern
Image 2 – Higgs boson decay. Source: atlas.cern

Code

In addition to p5.js’ two default functions (draw() and setup()), the project comprises of one additional function and four classes.

  1. OuterShell class
  2. Circle class
  3. Particle class
  4. Pattern class 
  5. Draw_beam function

OuterShell Class

I began writing code for the project by completing OuterShell class at first. It is a class that represents the outer rectangular-shaped structure of the lateral cross-section of the collider shown above. The class depends on five attributes and one display method that draws rectangle(s) using the information fed into its attributes. The display method makes use of two transformations — translation and rotation — in order to make the rectangles rotate around a fixed point (here, it is the center of the canvas). Thus, when objects are instantiated, stored and displayed using this class, it appears that a set of inclined rectangles are revolving around the core of the detector.

// Reset the canvas using push() and pop()

push();
translate(canvas_w / 2, canvas_h / 2);                // Move the origin to the middle of canvas
rotate(ANGLE);                                        // Angle of rotation                               
fill(random_r_val, random_g_val, random_b_val);       // Fill the shape
noStroke();
rect(this.x, this.y, this.length_, this.width_, this.roundness);         // The fifth parameter determines the roundness of edges
pop();

ANGLE += 3;

Circle Class

The Circle class is relatively a simple implementation, as it consists of three attributes and one display method. The primary challenge here was to implement fill() function on each circle individually. Even though I used multiple fill() functions, only the final color would cover the largest circle on the canvas, and since I planned on using different fill colors for different circles, the use of if-conditionals to manually specify RGB values helped me solve this problem. Here, I used radial measurement to determine which RGB values go with which circle.

Later, four concentric circles are instantiated in the setup function. In doing so, a list of radii is stored in a list and looped through using another for-loop to create and store circles in their corresponding list. Finally, in the draw function, using another for-loop, the display() method is called on each circle in the list and is displayed on the canvas.

 

Particle Class

This class is similar to the OuterClass class in terms of its display() method, yet a lengthy one. It depends on three attributes and two methods. The first method, titled display(), is used to create a set of red particles (ellipses) that revolve around the core, which has been done using a similar algorithm used in the OuterShell class, whereas the second method, titled disperse(), is related to free-flowing particles (ellipses) on the entire canvas. The idea for the disperse() method is such that there are particles around the detector, in reality, thus I implemented this method to represent the existence of different kinds of particles in and around the detector. Here, I update the x and y coordinates of free-flowing particles inside the disperse() method, which provided mobility to individual particles.

// METHOD 2

disperse() 
{
  stroke("white");
  ellipse(this.x, this.y, random(0, 0.5), random(0, 0.5));
  
  // Update x and y values simultaneously
  this.x += this.speed;
  this.y += this.speed;
}

Pattern Class

This is by far the most interesting and tedious section of the project. Initially, I was planning to draw either spiral or arc-related designs, but I went with a new pattern to differentiate this project from previous assignments.

The class depends on three attributes and consists of a single display() method. Here, I used one of the attributes (count) to determine the number of lines drawn. And, using a combination of for-loop and line() function, with some basic trigonometric calculations to determine two points of a line, a number of linear segments are drawn inside a circle of radius 80 (modifiable). Since its objects are instantiated and displayed inside the draw() function, which is called a certain number of times in a second, it appears as if the lines are mobile in nature.

display() 
  {
    let radius = 80;                              // Radius whichin which lines creation is confined
    
    push();
    translate(canvas_w / 2, canvas_h / 2);       // Move the origin to the middle of canvas

    // Loop execution determined by this.count attribute
    for (let i = 0; i < this.count; i++) {
      let ANGLE1 = random(0, 2 * PI);            // Angle value that determines x and y coordinate of Point 1
      let point_1_x = sin(ANGLE1) * radius;      // x-cordinate of Point 1
      let point_1_y = cos(ANGLE1) * radius;      // y-cordinate of Point 1

      let ANGLE2 = random(0, 2 * PI);            // Angle value that determines x and y coordinate of Point 1
      let point_2_x = sin(ANGLE2) * radius;      // x-cordinate of Point 2
      let point_2_y = cos(ANGLE2) * radius;      // y-cordinate of Point 2
  
      strokeWeight(0.4);
      stroke(234, 148, 14);
      
      // Drawing line from point 1 to point 2
      line(point_1_x, point_1_y, point_2_x, point_2_y);
    }

    pop();
  }

 

Draw_beam function

Finally, to add to the final effect and incorporate user interaction, this function is implemented so that a random number of lines (in a range of 3 to 7 inclusive) that lead to the core of the detector are drawn. These lines imitate the actual beam of light that is radiated inside a reactor when particles collide with each other. Thus, when the user clicks on the canvas, different colored lines are generated and displayed on the screen. The function makes use of if-conditional statements to pick a certain color for each line.

Here, the frameRate() function’s argument can be modified to control the speed of the canvas element. If a lower frameRate is used, the output may seem laggy. However, for this assignment, frameRate is set to be “5”.

Reflection

Overall, I am satisfied with the final output. I was prepared to start working on this project on Friday, but the brainstorming phase got an unforeseen amount of extension. Thus, I believe, I invested a good portion of time in planning. Also, since the project is divided into fixed classes and dependencies are handled separately, I am happy with the project.

  1. If I get to improve or re-work this particular project, I will focus on the following ideas and technicalities to further improve the final output:
    When the user clicks on the canvas, lines are drawn from random particles to the center of the core. However, with a little bit of work, it can be modified so that when the user clicks on a particular particle, a line will be drawn connecting it and the core of the reactor.
  2. Similarly, using 3D libraries, an extra dimension can be added as a result when the mouse is clicked, the canvas spans 360 degrees to give a thorough animation of the simulation.

 

 

Assignment 3 – Generative Art

Concept

I was originally playing around on p5js with Perlin nose trying to learn it, until it finally began taking shape and I thought of the opening credits of Monsters Inc., specially the scene with the doors being at the end before the title of the movie was shown. (I’ve put a link to the video, it is from minute 1:05 to around 1:10-1:15)

https://www.youtube.com/watch?v=FCfv5P8GXU4
With my inspiration clear, I looked for ways to add different colors while still being in the same color pallet, and that’s when I found this sketch of a background changing colors with Perlin noise.

The part that was of most relevance to the code was the following, as it allowed me to get the colors I wanted

let n = noise(offset)
 colorMode(HSB)

 background(n*360, 100, 100);

 offset += 0.01

 

code

As for the code, that was a completely different adventure. It was originally difficult to try and find an idea, or get my grasps on how things worked with Perlin noise, specially with getting my head around mapping.

I think that my code ended up how it did as I did not place anything to make the area the ball moved in back to the background, but I believe it made it work better.

My code ended up looking like this:

//This code was in part done while learning about Perlin noise by the Coding Train on youtube and following his tutorials//

let xOff = 0; //offset on X axis//
let yOff = 10000; // offset on Y axis//
let offset = 0; //offset for color//

function setup() {
  createCanvas(400, 400);
  background(0);
}

function draw() {
  // used the mapping function in order for the Perlin noise to scale around with the canvas //
  let x = map(noise(xOff), 0, 1, 0, 400);
  let y = map(noise(yOff), 0, 1, 0, 400);

  n = noise(offset); // declared the offset in for the colors//

  // found out about HSB coloring with Perlin noise by this sketch https://editor.p5js.org/amcc/sketches/XcXWNTPB-//
  colorMode(HSB);
  // I wanted to make the strokes also change colors, maybe it could be done with the same result with noStroke//
  stroke(n * 260, 100, 100);
  //Making the offsets change a bit in order for the circle to move around the screen//
  xOff += 0.01;
  yOff += 0.01;
  //filling in with Perlin noise in order to have different but somewhat matching colors//
  fill(n * 255, 180, 180);
  ellipse(x, y, 50);

  offset += 1;
}

My only one complain is that I wish I could have figured out how to use a specific color pallet, as having more variations would have been interesting.

Art Works

I made multiple versions of the code, either by adding or removing some strands of code.

This was the first attempt and what lead to me finding my project:

No color, just black and white, looks kinda 3D

The second version I made was similar, as it had lines and in a white canvas, but the ellipses were filled with colors, this is the second version of my design:

Only added color to the circles

And the final version of it came a bit later, where I made the lines also change color, and made the background black in order to make the colors pop-out more:

In a black space with seemingly no filling, looks a bit trippy

And here is a loop version of it:

reflection/future work

Personally I am happy with my end result, however I wish I could have understood more the process of creating it instead of randomly stumbling into it.

Secondly, I would have liked it to be able to use different color pallets, however I lack the skill and knowledge to do so at the moment.

Lastly it would be interesting if I could have added a mouseX or mouseY function, but with the time constraint I did not want to.

Object-oriented artwork

Concept –

I recently watched a documentary called Trainwreck: Woodstock ‘99 on Netflix about how the 1999 Woodstock recreation completely backfired in comparison to the iconic 1969 concert, and I heard a song from the documentary called Woodstock by the band Matthews’ Southern Comfort. This inspired me to create some randomly generated ‘peace & love’ themed artworks using object-oriented programming.

I created 3 pieces. 2 that randomly generate images and shapes every time you click the play button, and 1 that constantly adds images on a loop without stopping.

Code highlight –

function setup() {
  createCanvas(400, 400);
  background(255);
  for (let i = 0; i < 1000; i = i + 1) {
    // designates spots for random circles and images being generated (repetition); i is 0, it has to be less than 1000, it will move by 1 coordinate each time a shape is generated

    image(green2, random(width), random(height), 50, 50);
    image(blue1, random(width), random(height), 50, 50);
    image(smile, random(width), random(height), 50, 50);
    image(pink2, random(width), random(height), 50, 50);
  }
}

Embedded sketches–

Randomly generated artworks:

(every time you click the play button it will randomly generate a new piece)

(this one is my favorite)

I managed to maintain warmer hues for this artwork because I inputed the ‘i’ value into the fill for the ellipses.

Loop artwork:

Reflection and improvements –

  • I struggled mostly with the loop artwork, because every time an image was plotted, it was placed within a designated proximity of another image, and I couldn’t figure out how to change that to be more random. I even inputted the push and pop feature I learned from The Coding Train but that didn’t seem to change anything.
  • Trying to slow down the speed in which the images appeared in the loop artwork.
  • I feel that I need to figure out how to make more advanced pieces, but I don’t have enough knowledge to be able to execute what I imagine.
  • I’d also like to make something beyond randomization.
  • All the pieces I’ve made so far feel very 2D, I’d love to learn more about how to make my work feel more 3-dimensional.
  • Although The Coding Train videos do help, I feel that I need way more time and practice to learn how to code proficiently— or at least to the level of my peers. I don’t fully understand coding language yet— and trust me, I’M TRYING!

Michael Gary Scott on Twitter: "Whatever. I'm not gonna cry about it. I already did that in my car on the way home." / Twitter

[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 2: Loop Art

Concept

For this project, I was inspired by figure skating ice, where many patterns are left by the blades of skates from jumps, spirals, and spins. I decided to make an art pattern that resembles the after-spin effect like in this video:https://www.youtube.com/watch?v=ss_3secVE_c

I also wanted to make an effect of ice flakes during the interaction of blade and ice, so there are mini circles going around.

For the execution of the code, I used the tutorial for making spirals(https://www.youtube.com/watch?v=wSNYOYlRsBE) and made loops out of them.

Code Snippets

Code for spiral loops

var angle  = 0.0;
var offset = 10;
var scalar = 1;
var speed = 0.01;   

function draw() {
  for(let i=10;i<=width; i=i+50){
    stroke(153,204,255);
    var x = offset + cos(angle) * scalar;
    var y = offset + sin(angle) * scalar;
    ellipse(x + i, y+ i,1,1);
    angle += speed;
    scalar += speed;  
  }
}

I also was playing with bezier and spiral formula, but combining them together went chaotic, so I only left the formula and a funny string tornado appeared:

Reflections

For future improvements, I would like to add user interactions where users could point out where the spiral starts. Also, I want to learn to work with frames for more fun animations. I also understood that a lot of animations require the usage of complex formulas and trying iterating code again and again. That’s why, I really want to untangle this complex process.

 

Week 2: ‘Rhythm and Chaos’: An Attempt at Generative Art

The idea:

For our second assignment we were tasked to create a generative art piece using loops in p5js. For me, art has always been a creative expression which is not strictly restricted to visual perception. One of my favorite art forms (and the one I spend the most time indulging in) happens to be music. So I wanted to incorporate music into this assignment from the get go. This is what I ended up creating after long hours of working this weekend. A simple click and it comes to life!

The process:

I started by looking up the Coding Train‘s videos (of course!) for incorporating music into my p5js file. I found about the preLoad() function which helped me upload and play one of my favorite tracks, ‘La Cuidad’ by Odezsa right inside the browser.

Next I knew I wanted to create something that would respond to the music. After a bit of searching Dan Shiffman from the Coding Train came to the rescue again. I spent an entire day learning about Fourier Transforms and the built in FFT object from this video and the reference page on p5js’s site:

This taught me how to display waves based on amplitude, frequency of the music. To make it more visually appealing I used for loops and played around with trigonometric functions (sine and cosine) to transform the straight line of waves into a circle. This gave me a half circle and I had to repeat the for loop with a negative value of sine to get a full circle. I’m sure there must be a more efficient way to do this, but this is how far my brain cells could go. I also used map() function with help from the reference page (and a lot of trial and error) to keep the waves within the bounds of the canvas. You’ll notice most of the values are hard-coded so this of course is an area I could improve on.

When I listen to music, it almost transports me to a different realm; I feel lost and immersed but in a good way. With a day to go till the deadline, I wanted to incorporate some of that feeling into this piece. And what better than getting lost in a star field in space?! As a form of habit I searched up ‘Star Field Coding Train’ on YouTube (God bless Dan Shiffman). I watched this video but it was full of advanced functions and most it flew past my ears. I do, however, know how to create classes (I did that for my first assignment too). So, I created a class for the stars and since I am familiar with vectors, velocity, and acceleration from high-school Physics, I read into the reference pages in p5js and figured out how to make stars fly towards the screen from the resting circumference of the circle. Here’s a code snippet of the class:

class Star {
  constructor() {
    //a fixed scalar multiple for uniform visual effect
    this.start = p5.Vector.random2D().mult(150);
    //vector for initial velocity
    this.velocity = createVector(0, 0);
    this.acceleration = this.start.copy().mult(random(0.001, 0.00001));
  }

  move(check) {
    this.velocity.add(this.acceleration);
    this.start.add(this.velocity);
    if (check) {
      // adding more speed if the .getEnergy method returns higher frequencies, by just adding more of the same method
  this.start.add(this.velocity).add(this.velocity).add(this.velocity);
      // this.start.add(this.velocity);
      // this.start.add(this.velocity);
    }
  }
  //stars i.e. ellipses of random sizes
  display() {
    noStroke();
    fill(255, 255, 255);
    ellipseMode(CENTER);
    ellipse(this.start.x, this.start.y, random(2, 5));
    // console.log(this.start.x, this.start.y);
    // line(this.start.x,this.start.y,(this.start.x + 1),(this.start.y + 1));
  }
}

Another part of the code which I like is using the .getEnergy() method of the FFT object to increase the velocity of the stars depending on the frequency of the track. I created a boolean statement to return True or False if the music crossed a certain frequency. If True, I increased the velocity by repeating the velocity method.

//FFT methods
let waves = fft.waveform();
fft.analyze();
//star speed responding to beats
let bounce = fft.getEnergy(20, 200);
let p = new Star();
stars.push(p);

  for (i = 0; i < stars.length; i += 1) {
    stars[i].move(bounce > 230);
    stars[i].display();
  }

Things to improve on:

The star field Dan Shiffman demonstrated was more beautiful, and stars had a trailing and fading effect to them. I think I can spend more time trying to learn all those functions for future projects. Also, a lot of the conditions in the for loops are hard coded, which I will try to improve on for future projects.

Outro:

For finishing touches, I randomized the R,G,B values of the stroke color and the stroke weight to create a vibrant sense of chaos. I think when the piece comes to life, this will give the audience a sense of rhythm within chaos, which music brings to my life every single day.

Assignment 2: Art Patterns Using Loops

My idea was to create a spiraling pattern of mini-circles that change color when the user moves the mouse. This idea was motivated by the milky way galaxy that appears in a spiral form.

The Milky Way Galaxy | AMNH

After thinking through several ways to color the patterns, I ended up changing the colors by random and at the same time with the movement of the mouse pointer. The code for the coloring is shown below:

The embedded sketch of the assignment:

Reflections:

It’s interesting how the frame rate changes the perception of the art. I will explore the different frame rates and how they affect my perception of the design. Also by changing the angle of the circles and the speed at which they change, the design changes in many different ways. I will most likely explore the different designs by changing the angle and speed.