Week 2 – Artwork using Loops

Concept 

For this artwork, I wanted to create layers on top of each other that merge to form a piece of art. Each layer was developed using repeating shapes with a for or while loop. This was inspired by some geometric artworks I found online. While most of them had one repeating element such as a circle or square, I thought why not make several layers and merge them to form a different art piece? Some work that inspired me is:

Interactivity
Moreover, I wanted to create a monochromatic art piece with a pop of color that the user can add. So, the entire piece is shades of black and white and these colors blink/alternate. Moreover, the user can press the mouse to add colored circles throughout the canvas however, these disappear when the mouse is released. But a glimpse of them can be seen in the back through the spaces in the previous layers. This way, the users’ interactions bring a pop of color to the otherwise monochrome canvas.
Another form of interaction I added was a slider that allows the user to change how fast or slow the artwork blinks by changing the frame rate.

My Artwork


Code

Code I am particularly proud of is the following:

function getCircles(posX,posY,circleWidth) {

//alternate color of each circle between black and a random value between black and white
colorBlack = true;
noStroke();

//loop 20 times, each time increasing the width of the circle centered at x and y
for (let i = 20; i>0; i--) {
//alternating colors
if (colorBlack == true)
{
colorBlack=false;
fill(random(10),random(15),random(15));
}
else {
colorBlack = true; 
fill(random(255));
}
//making the ellipse
ellipse(posX,posY, circleWidth*i, circleWidth*i);
}
}
//draw a flower at x and y using rotating ellipses
function drawFlower(posX,posY){
  
  noStroke();

  for (let i = 0; i < 10; i ++) {
    fill(0,127);
    
    ellipse(posX,posY,10, 60);
    rotate(PI/5);
  }
}

//helper function to draw a flower 
function drawFlowers(posX,posY)
{
  translate(posX,posY);
  drawFlower(0,0);
}

//function to create a bunch of flowers in bottom-left
function getFlowers(){
  drawFlowers(50, 350);
  drawFlowers(30, 30);
  drawFlowers(-60, 10);
  drawFlowers(0, -80);
}

With these functions, I used loops to create blinking circles and flowers using rotate and translate as well. As a whole, the assignment turned out to be very fun to make.

Reflection and future improvements

I found this assignment to be exciting as I got to play around with loops – which is something I really enjoyed doing in the first assignment too. Also, it allowed me to express my creativity and further enhance my artwork using interactivity. Some aspects I can improve in the future include optimizing my code further to use loops to position the flowers and the sets of circles on the canvas. For now, I hard-coded the positions but in the future, I want to make the canvas more responsive by using values that are in terms of the width and height variables. Further, I want to learn how to use make the number of elements on the canvas increase/change with time.

HW2 – Generative Art

Concept

I have started my implementation of the art work from one of the works from Programm-Information21 suggested by Professor Shiloh. It is shown below.
At first, I  replicated  it  trying  to copy  the  idea  of squares populating my  canva  with  various  density. It turned out to not be so exciting, so I have decided to play around with shapes and then I sticked to the idea to use ellipses. My final sketch uses only ellipses.

Different parameters for ellipses gave different visuals, and for my primary part of sketch I attempted to replicate ongoing flames. Background color is set to orange and a number of black ellipses with different parameters moving in a random fashion are responsible for the final effect.

Code for the Fire Imitation

background(249, 94, 4);
fill(0);
for (let x = 0; x < width; x = x + 5) {
  for (let y = 0; y < height; y = y + 5) {
    if (y < height / 4 + 10) {
      ellipse(x + random(width / 20, -width / 20), y, 8, 10);
    } else if (y < height / 2 - 30) {
      ellipse(x + random(width / 20, -width / 20), y, 6, 10);
    } else if (y < (3 * height) / 4) {
      ellipse(x + random(width / 20, -width / 20), y, 4, 10);
    } else {
      ellipse(x + random(width / 20, -width / 20), y, 3, 10);
    }
  }
}

As I mostly implemented the fire animation in class and just changed it a bit at home, I have decided to add something using key controls as well. So, to introduce a bit of contrast to fire, I coded falling rain drops to imitate rain to some extent. I did some quick research on p5js to use Classes and functions to code behavior for each rain drop as an object. It is again ellipses.

Code for Rain using OOP

class Rain {
  constructor() {
    this.x = random(0, width);
    this.y = random(0, -height);
  }
  create() {
    noStroke();
    fill(140, 223, 232);
    ellipse(this.x, this.y, random(3, 6), random(3, 10));
  }
  fall() {
    this.y += random(10, 30);
    if (this.y > height) {
      this.x = random(0, width);
      this.y = random(0, -height);
    }
  }
}

“Rain” activates when a user presses the mouse and stops upon its release. You can check the full sketch below.

Reflection

My final sketch is nowhere near close to the work I got inspiration from. For me, it shows that we may start at one point and end up deviating from our designed path yet enjoy the process. It is certainly exciting that such simple code may produce interesting results.

Future Improvements

I am quite satisfied with the flame animation, yet for the rain part I feel it can be improved further and there it may make sense to add ground, sky, and other attributes to give it a look of something more real, rather than completely artificial.

Loops – Aigerim

Inspiration

For this project, I recreated an artwork from ProgrammInformation. It is a collection of stars that are scattered throughout the screen. I took the idea of a static image and decided to make it dynamic. I also randomized the number of stars in each iteration and the shape of the star, thus creating infinitely many unique similar artworks.

Process

It was a bit tricky to figure out how I am going to angle the lines of each star and make them appear with random rotations and lengths. The way I went about is that I picked a random point (x and y coordinates) where the star would be centered and drew lines from that point to a new, random point within a given range (as can be seen on the code below).

function cluster(x, y) {
  for (let i = 0; i < 20; i++) {
    dx = random(-25, 25);
    dy = random(-25, 25);
    line(x, y, x + dx, y + dy);
  }
}

Each line in a star is away from the center at most 25 pixels in both x and y, and ranging the random value of that distance (dx and dy respectively) from negative to positive enabled me to create lines around the center in all directions. Only the number of lines in each star remain constant (20), but everything else is randomized, creating a unique image at each new frame.

Reflections

Overall, I am proud of the solution I came up with in creating the lines, as it does not seem to be a trivial or traditional way to go about it, at least for me. If I were to work in this further, I would love to incorporate some interactivity (e.g. making the frame change whenever user clicks on the image) or adding some color.

HW2: Loops

CONCEPT

I took inspiration from this one example shown in the COMPUTER GRAPHICS and ART magazine for May, 1976  suggested by the professor. It made me think of buildings and cables under walls. In my sketch, I attempt to imitate a nightlife of a residential building, with the light in the windows randomly turning off and on, and the cables exposed over the walls indicating some activity.

IMPLEMENTATION

I created three functions to draw each element of the sketch: cables, windows, and walls. FrameRate function is set to 1 because the change is too fast-paced otherwise and the sketch looks less like a building in a night time.

I started by making the overlapping cables, which created the outline for the brick walls and windows. The cables are done in a for loop nested three times: the first time to draw multiple rectangles over itself, the second time to make a row of those rectangles, and the third time to make it a grid. The rectangles overlap with each other in a row, to make a narrow compartment for a window to fit snugly into. The outline of the rectangle is different each time because, in my mind, it makes sense that a change of color signals whether the cable is on or off.

For windows, I have used a nested loop to make a grid of rectangles. An array of two colors and a random function are used to update the fill value. This helps to imitate the lights being turned off and on in each apartment unit and gives the building some life.

I had the most struggles drawing the bricks. Initially, I wanted to make a 6 by 4 grid of brick walls so that they don’t go beneath the windows but stay separately from one another. However, when I tried implementing that, the editor would crash. I assume that it’s because I have nested the for loop 4 times. I tried a few more times until I realized that it would be easier to make a singular 50 by 27 brick wall and call this function before the other two.

Essentially, all three of my functions are similar to one another. I attach the brick wall function snippet because it took me the longest to come up with.

//drawing the bricks
function brickBuild() {
  noStroke();
  fill(222);
  let brX = 0;
  //initial Y indentation
  let brY = 33;

  for (brGridH = 0; brGridH < 50; brGridH++) {
    //move the row down
    brY = brY + 9;
    //initial X indentation for each row
    brX = 28;

    for (brGridW = 0; brGridW < 27; brGridW++) {
      //draw 12*8 brick
      rect(brX, brY, 12, 8);
      //move to the left
      brX = brX + 13;
    }
  }
}

WHAT WOULD I CHANGE

Perhaps, to make the sketch imitate a residential building more closely I could make each of the windows update the fill value at a different point so that they would change the colors asynchronously. The cables could do the same things (change asynchronously), but I would also add a pulsation effect when they change their color and width/height values.

Week 2 – Loop Art

I have thalassophobia, the fear of giant bodies of water. So, if ever asked to choose between mountains and the sea (like on those personality quizzes), I will, without a doubt, choose the mountains. However, like most people, I love nature. Having grown up in a small village I am no stranger to its wonders and in my 20 years of being on the Earth, I have grown my appreciation for even the smallest drops of dew condensed on an unripened plum. So, for this assignment, I choose to focus on both mountains and the sea in order to explore loops and conditionals in p5js:

The Sea

Challenges

To start off, I didn’t animate the sea. Rather, I just created a stationary sine curve. Then, sine curves. I didn’t quite understand how to make them move, so I watched this video by Professor Daniel Shiffman and implemented his motion technique to my sine curves. To make them move in the opposite directions, I first started with graphing them out of phase, which did not work because they would move in the same direction. By using the modulus function, I was able to move adjacent rows in opposite directions, which gave the animation an interesting effect. A big obstacle was also the background. Since fill() and stroke() can go beyond the scope of the function they are in, it took some time to re-read the code in order to remove stroke() and strokeWeight() from elements they were not supposed to be on. Lastly, since I used curveVertex() for the sine waves, I was unable to fill the sea properly. So, to get around that, I increased the stroke and used scale() to make the waves slightly bigger without seeing the background underneath.

Reflection

The sunset, although it does not look completely realistic, is still very beautiful. By looking up the hexadecimal values for the sunset colours I was able to create ellipses which imitate the sky around a setting sun. I placed a rectangle above the canvas with a varying alpha (transparency) which made the sunset more realistic:

// Sunset color over the sea
noStroke()
fill(4, 97.7, 65.9, map(mouseY, height, 0, 0.1, 0.4))
translate(100,100)
rect(width/2, height/2, 800, 1000)

Although I tried making a gradient, it did not look good, so I stuck with the simplified version. In the future, I wish to understand how to make gradients without the help of external libraries and make the motion of the waves both horizontal and vertical compared to the currently only horizontal ones.

The Mountains

Challenge

To start off, understanding how to graph noise() was very challenging. To understand noise(), I once again watched Professor Daniel Shiffman and his series on noise(). They were extremely helpful in understanding how to graph noise without having all the curves look the same. Although I understood how to store the points on the canvas and how to graph them, the amplitude of the waves (y offset) was not working properly. Fortunately, I realized that I was not the only one interested creating noise() curves and I solved my issue by contrasting my code with the example on this page. After graphing my mountains, I realized that they would not fill completely. After some time, I realized I could use rectangles underneath the curves in order to make them completely filled. Lastly, working with RGB is the easiest when dealing with a single shade of blue. By reading about different color modes in p5js, I was able to figure out how to gradually increase the brightness of my blue through the use of colorMode(HSB).

Reflection

In class, we made “buttons” by constraining the mousePressed function on an ellipse or rectangle. For this assignment, I wished to create the option to, in a way, shuffle the mountains and the stars in order to get new pieces of art, if they can be called that. I created a button (“Generate new”) which can be pressed to do just that:

let button = createButton("Generate New");
button.position(0, h - 20);
button.mousePressed(loop);
button.mouseReleased(noLoop);

The button loops draw() when pressed and stops after being released which showcases the noise() function a lot better and its weight on standard distribution, i.e., distribution around the center. In the future, I wish to combine the two artworks and create a bay or lagoon that encompasses both the concept of noise() and water motion inspired by sine curves.

Week 2 – Generative Art

Inspiration & Execution

I was looking through the documents given in the syllabus for inspiration, and as I was looking at the patterns and shapes, I was transported back to my childhood days spent playing around in Microsoft Paint. Back then, I did not have access to the internet, and as someone with no artistic skills, I would just randomly draw rectangles of different sizes over and over again.  The “painting” that I used to make on Microsoft Paint looked somewhat like this:

This experience inspired me to try and recreate those old drawings, but this time using only my keyboard. I was able to use the random number generator that was taught in class, combined with my own research on frame rates and frame counts, to create a piece that alternates between black and white backgrounds. I did not want a single rectangle appearing every frame so I played around with a for-loop till I found the perfect balance between the number of rectangles per frame and the frameRate. I also subtracted 50 from the random numbers generated for the x-coordinates so that some of the rectangles start outside of the frame.  The final product looks like this:

Reflection

Even though this is a simple piece and I spent way less time on this than my first project (self-portrait), I still like it much more because of how connected I feel to this. Something that I am particularly proud of this time is that I was able to implement all that I had initially thought. Moreover, adding a pop sound every time a pair of rectangle pops was something new to me and I am really proud of that as well. Something that I would like to possibly change for the future is to add interactivity to it and instead of just being black and white, I would want to add different colored rectangles with different opacity in order to make it more colorful. Furthermore, I would want to randomly select different shapes (and hopefully add a better sound instead of the “annoying” pop sound).

Assignment 2: Geometric Patterns – symmetry, patterns, randomization

The concept:

I looked through the pdf’s attached on computer graphics and saw a piece which inspired me a lot. This is where I drew my inspiration from:

Initially I created patterns of squares of one distance reaching for the four different corners. I decided to create a symmetric and ordered pattern which causes some sort of optical illusion.

Here is that piece:

Then I moved on to create the same four cornered patterns but with different distances between the squares – doubling and halving the distances.

This was with the intention of creating something which very closely resembles the inspiration piece. I randomly chose the patterns without thinking deeply about the pattern number I was choosing, then I arranged as I saw fit by changing the patterns into a piece which I liked best.

Here is the piece resembling the inspiration source:

Finally, after watching the video which talked about chance and randomness in art I was inspired to create an animation which randomly chooses a different pattern for each square in the canvas every 2 seconds. I think allowing randomness choose its course makes for a very interesting art concept.

Here is the modified version after watching the Chance in Art talk:

Curiosity got the best of me once again, and I wanted to see the above piece if the squares were of homogenous size and distance. I made the canvas smaller in order to focus more on the patterns which are created when the squares align. This one also changes every 2 seconds.

Here is what this looks like:

Reflections:

I truly allowed myself to indulge in my curiosity and inspiration from both the piece which I attached in the beginning but also in the talk given by Casey Reas on Chance Operation.

What initially began as a piece to itch the part of my brain which needs symmetry, then proceeded to become a demonstration of code in a way which imitated the first piece of inspiration, then became an exploration of chance and pattern creation.

I enjoy my 3rd piece the most, because it creates numerous variations of the initial inspiration source, and I believe it shows the work of chance in a very beautiful way by creating patterns.

The reason why I created the 4th piece was because I noticed that when the patterns were of homogenous size and distance and they were next to each other, they align to form interesting patterns, so I had the idea to create different patterns which only included squares of homogenous sizes. I see now that the most noticeable patterns are when the squares are more frequent and the distances between them are smaller, and the largest patterns barely align to create a pattern, but as a whole still create an interesting show of chance.

Challenge:

I had only one technical challenge initially because I started creating the mini patterns inside the squares using ‘for loops’, but quickly realized that was a mistake when the squares overlapped. Then I chose to use while loops instead because I have 3 different variables being incremented by different values. Here is one excerpt:

function filler1(x, y) {
  var i = x;
  var j = y;
  var k = 100;
  while(i<x+60)
    {
      square(i,j,k);
      i+=10;
      j+=10;
      k-=15;
    }
}

Where x and y determine the coordinates of the square, which get randomly chosen in setup (first two pieces) or randomizer functions (last two pieces).

I did, after all, utilize a ‘for loop’ to randomize the choices for each square:

function randomizerCall() {
  
  for(let i = 0; i<601; i+=100)
    {
      for(let j =0; j<301; j+=100)
        {
          randomizer(i,j);
        }
    }
}

Thankfully this project did not give me many technical challenges. The largest challenge was fulfilling my curiosities, because as soon as I was wrapping up one piece my curiosity would wonder about a variation of the piece which might make it more interesting – hence the 4 different pieces.

Week 2: Generative Art

Concept

The idea of the project was to simulate stars in the night sky. Due to the rotation of the Earth, if we were to point a camera at a clear night sky full of stars, we would capture the movements of the stars. This movement resembles a circle with the centre at the North Star. I proceeded with the image of multiple concentric yellow circles which transformed to become more colourful as I wrote the code. The final image also resembled the rings on a heavenly body, such as Saturn. Also, if one were to look at it closely, it also appears to resemble an impressionist version of mandala art.

Code

Tracing the path of hundreds of stars was the most critical and the most difficult process in the project. In order to do it, I had to move the stars independently of one another. The simplest solution was to make each of the star as a single object. Thus, I made a class called Star and added attributes to it.

class Star {
  constructor() {
    // each star will have a random distance from the center
    this.radius = random(width);
    
    // each star has a random co-ordinate relative to the center
    this.xpos = center_x + random(-this.radius, this.radius);
    this.ypos = center_y + random(-this.radius, this.radius);
    
    // Calculating the angle of the star relative to the center.
    // A random constant is multiplied because without it the stars seems to only assume angle between -90 and 90 degrees. Try running the draw() function without this constant only once.
    this.angle = atan((center_y - this.ypos)/(center_x - this.xpos))*random(4, 9);
  }
  
  // function to display the star
  show() {
    noStroke();
    // changing color with respect to the count variable
    if (count % 100 === 0) {
      fill(color(random(10, 255), random(10, 255), random(100, 255)));
    }
    
    // star has a random diameter.
    circle(this.xpos, this.ypos, random(1, 3));
  }
}

This way, each star would have its own x-position, y-postition, radius and angle which can be modified independently of the others.

I proceeded to create hundreds of stars which would be displayed onto the canvas.

// count will change the color of the path traced by the stars.
let count = 1;

let num_of_stars = 200;

// co-ordinates of the center from where the stars will trace a circle
let center_x, center_y;

// will contain all the star objects.
let all_stars = [];

function setup() {
  createCanvas(700, 700);
  background(0);
  
  // centering the stars on the geometric center of the canvas
  center_x = width/2;
  center_y = height/2;
  
  // creating stars and appending it to the array
  let i = 0;
  while (i < num_of_stars) {
    all_stars[i] = new Star();
    i++;
  }
  
  // always start the trace with yellow.
  fill("yellow");
}

The while loop would create new stars and append it to the all_stars array.

function draw() {
  // modifying the attributes of each star, one at a time
  for (let i = 0; i < all_stars.length; i++) {
    let current_star = all_stars[i];
    
    // tracing a circle from center using the radius and the cosine and sine function
    current_star.xpos = center_x + current_star.radius * cos(current_star.angle);
    current_star.ypos = center_y + current_star.radius * sin(current_star.angle);
    
    // displaying the star onto the canvas
    current_star.show();
    
    // varying the angle to trace a circle
    current_star.angle += 0.01;
  }
  
  // incrementing count which is used in changing the color of the stars.
  count += 0.5;
}

The for loop will loop through all the stars, changes their attributes (essentially their position which traces a circle) and display them onto the canvas. The stars made a circle, as I implemented the change in x and y position through their polar co-ordinates counterpart in terms of radius and angle.

current_star.xpos = center_x + current_star.radius * cos(current_star.angle);
current_star.ypos = center_y + current_star.radius * sin(current_star.angle);

These two lines of code can be modified to create various other patterns and curves. For example, if we square the cos and sin in the function, we would receive a thicker circle, almost pixelated.

This looks almost like a mandala art (but not quite). Similarly, if we invert the cos and sin function (power -1), we would get something that resembles a top-down view of a well lit road junction.

Future Improvement

While I was messing around with the functions, I realised that there were many combinations that could be form with it. The two aforementioned modifications were two of the most noticeable ones. This called upon an improvement into the code, which has to do with the interactivity of the art. The idea would be to allow user to chose the function they would want to use. For instance, have a button to change the function from a cosine to a tangent.

Assignment 2: Colorful Illusion

This week I used for loops to create a popular illusion. Looking at the sketch you can see that some of the white circles start seeming as if they are black while all of them are white. This is a common illustration of optical illusion called lateral inhibition. Since the whole illusion can be done in the setup function, I wanted to add some complexity. When clicking on the screen, the circles randomly change their color. A bit of a playful element I guess.

The code that I’m proud of is the way I connected all the variables to the offset variable. By changing offset you can get either more of smaller circles with similar size of lines or less of bigger circles with bigger lines. Also, the user can change the window size and the sketch will still make perfect sense.

I’m proud of the fact that creating the illusion only took me 2 loops with singles lines.In the future,  I would like to make the interaction less random. As in making the circles change color one by one in a timely manner. Also, include the user interaction with keys and mouse movements.

Assignment 2 – Brief Encounter

The Concept

The idea for this project started from my fascination with how thin lines are presented digitally, and how slight variations in their arrangements can create interesting and surprising patterns. To start the project, I wanted to move two checkered squares across the canvas and have them overlap in the middle. As the checkered squares themselves consisted for two for loops to make all the lines in a geometric fashion. This was definitely one of the challenging parts: to move a bunch of lines across two for loops with set time intervals, where the number of lines moving aren’t predefined, and all of them must be moving together. I tried several approaches including implementing different pre-made functions like translate, but at the end, the best way to do it was through two global variables called movers.

Failed Attempt:

Final Solution:

The global variables are added to the construction of the line itself within the for loops, and incremented at the end of the draw, where the moverR and moverL are negative and positive to represent that they are moving in opposite directions.

The Sketch

Link for sketch: https://editor.p5js.org/mhh410/full/NI1puoEY6

The two squares move towards each other, meet for just a brief moment, where the hidden message “Hi” can be seen only when they completely overlap, and then drift apart, never to meet again (Hence, you must reload the page if you missed the message the first time!).

To play around with the sketch and explore the various behaviors the lines can make, I added a section called CONTROLS in the code.

Changing the speed controls the movement of the squares, and the sharpness controls how densely packed the lines are within the square, and this is what we can use to see various ways the squares overlap. The message however, can only be seen when the speed and sharpness are both set just right, and changing them too much results in not seeing any interesting results from the overlap.

Improvements

To add to this project, maybe an improvement could be adding a way to change the angle of the lines themselves. I’m sure more peculiar patterns could be created digitally if some lines were diagonal rather than just horizontal or vertical. I thought about adding a reset button, or making the squares hit the walls of the canvas and come back again, but then the encounter wouldn’t really be “brief”. Maybe adding some color to the design could also create some added surprise too.