Week 3 – recreating my pattern with classes

For this week we had to use the artwork from last year and incorporate classes into the code. Since I already explained my concept I will write it down very briefly here:

I was inspired to recreate one of the examples shown in class, and I did a series of 4 pieces of art which related to geometric patterns and symmetry as the one below. This one shows a different pattern each time the code is run, hence creating a new piece of art each time.

Since I revised last weeks’ work, there was no difference in the artwork (because that was the intention), there was, however, quite a difference in the code. I am a lot more pleased with the revised code, as it is easier to read and looks cleaner – grouping most of the repetitive things under the class, creating the squares in an array and keeping the setup() function cleaner.

class squareFiller {
  //constructor consists of the x and y coordinates
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

The constructor is very simple with just the coordinates as attributes.

//the first option of a pattern
  //the x and y coordinates are parameters as they will
  //be determined later in setup()
  //k variable determines how spaced each square will be 
  //from each other
  //the while loop determines the pattern by incrementing 
  //and decrementing respectively each of the variables
  //the rest of the fillers have the same idea but with 
  //different spacing and corners which they approach
  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;
    }
  }

This is the first of 12 similar filler pattern functions.

randomizer() {
    let num = floor(random(12)) + 1;

    print(num);
    if (num == 1) {
      this.filler1(this.x, this.y);
    } else if (num == 2) {
      this.filler2(this.x, this.y);
    } else if (num == 3) {
      this.filler3(this.x, this.y);
    } else if (num == 4) {
      this.filler4(this.x, this.y);
    } else if (num == 5) {
      this.filler5(this.x, this.y);
    } else if (num == 6) {
      this.filler6(this.x, this.y);
    } else if (num == 7) {
      this.filler7(this.x, this.y);
    } else if (num == 8) {
      this.filler8(this.x, this.y);
    } else if (num == 9) {
      this.filler9(this.x, this.y);
    } else if (num == 10) {
      this.filler10(this.x, this.y);
    } else if (num == 11) {
      this.filler11(this.x, this.y);
    } else {
      this.filler12(this.x, this.y);
    }
  }

The randomizer function randomly chooses one of the patterns for the square at hand.

//instantiating the objects in the array for
 //each square in the grid
 for(let i = 0; i<601; i+=100)
   {
     for(let j =0; j<301; j+=100)
       {
         arr.push(new squareFiller(i,j));
       }
   }
 //calling the randomizer function for each
 //square in the array
 for(let i=0; i<arr.length; i++)
   {
     arr[i].randomizer();
   }

The setup() function is quite simple, with these lines being the most important as they instantiate the SquareFiller objects in an array, then there is another for loop which calls the randomizer function for each of the objects – hence choosing a pattern for each square in the canvas.

The biggest challenge for me was thinking about how I was going to incorporate a class into this code. But after a bit of pondering and experimenting I decided to create a SquareFiller class, which determined the pattern of each square.

Furthermore, I faced the challenges of writing a class in JavaScript as I had never done that before. To solve this, I referred to the class notes, used the Reference of P5 and the internet and figured everything out.

Week 3 – Object Oriented Programming Art

Concept:

Object Oriented Programming (OOP) and art are two separate concepts to me. I have only ever used it to create games, or different data structures, so when it came to creating art, I was in an art block. Since OOP is extremely useful when it comes to motion of objects and graphics on the screen, I was immediately drawn to something dynamic. But what? Since all of my friends are taking Foundations of Science, I am continuously surrounded by physics. This month, the topic was circular motion. When I think about circular motion, I think about rotation and revolution of celestial bodies. Hence, for this week’s project, I have created a small work that depicts the motion of planets (Mercury through Neptune sorry Pluto 🙁 ) around the Sun.

The Solar System 

Link: https://editor.p5js.org/ajlasacic/full/GIWVhC73H

Challenges:

To start off, circular motion was hard to think about when working with OOP. Since I was working with many orbits, it was a struggle to spread them adequately across the screen. The model is obviously scaled down, it is an artistic representation of the system, but managing the distances between the planets and setting up the asteroid belt was really tricky and took some fiddling to get right.

  this.display = function () {
    fill(this.color);
    ellipse(this.x, this.y, this.radius);
  };
}

// Move objects in a circle by updating the angle
move() {
  this.x = this.xPos + this.distance * cos(this.angle / this.speed);
  this.y = this.yPos + this.distance * sin(this.angle / this.speed);

  this.angle++;
}

The asteroid belt was another point of concern. I wanted to contain it in one place, so that it can be considered one object. Although I could have just used for loops outside of the code, I created another class which made it easier to control the specific parameters of the belt such as the size and number of circles.

// Asteroid belt 
class Belt {
  constructor(m, n) {
    // Number of belts
    this.n_belts = m;
    
    // Number of asteroids in belt
    this.n_rocks = n;
    
    // Array for storing asteroid objects
    this.beltArray = [];
  }

  // Produces a 2d array - this.beltArray[] 
  add_asteroids() {
    for (let i = 1; i <= this.n_belts + 1; i++) {
      let belt = [];
      for (let j = 1; j <= this.n_rocks; j++) {
        belt[j] = new Celestial(
          width / 2,
          height / 2,
          random(2, 4),
          i * (start - 10) + 170,
          j * 130 + i * random(10, 15),
          random(12.5, 37.5) * rotation,
          random(100, 200)
        );
      }
      this.beltArray.push(belt);
    }
  }

  // Displays each meteor by calling Celestial
  display_meteors() {
    for (let i = 1; i <= this.n_belts; i++) {
      for (let j = 1; j <= this.n_rocks; j++) {
        this.beltArray[i][j].move();
        this.beltArray[i][j].display();
      }
    }
  }
}

Unfortunately, when I came to that point, my code got deleted. In all honesty, it was my fault since I did not save the file once before leaving my workstation. From then on, it took another couple of hours to get back to my original progress, but I was devastated for quite some time because a split second was all it took to lose hours of work.

I was struggling to create the trail effect. In the beginning, I was trying to write more code in order to make it appear behind the celestial object. In the end, I realized that if I decrease the alpha of the background, a nice trail should be left behind by the celestial objects.

// Opacity can change for trail effect of moving objects
  background(0,0,0, opacity);

Finally, in order to introduce some creativity, I wondered whether an orbit can be drawn for each planet. For some time I tried to create it within the class, but since my Belt class creates instances of the Celestial class, it would make an orbit for each asteroid as well. I settled for creating a separate orbit() function that uses the start variable to size the orbits. Unlike C++ I could not make getter functions, so I could not extract radii for the planets which is why I ultimately could not make everything resizable .

function orbits() {
  // Sun glow
  for (let i = 0; i < 50; i++) {
    fill(241, 93, 34, 3);
    ellipse(width / 2, height / 2, i * 1.3);
  }
  
  noFill();
  stroke(255, 255, 255, val);
  ellipse(width / 2, height / 2, start * 4);
  ellipse(width / 2, height / 2, start * 6);
  ellipse(width / 2, height / 2, start * 10);
  ellipse(width / 2, height / 2, start * 14);
  ellipse(width / 2, height / 2, start * 24);
  ellipse(width / 2, height / 2, start * 28);
  ellipse(width / 2, height / 2, start * 32);
  ellipse(width / 2, height / 2, start * 37);
  noStroke();
}

function mousePressed() {
  val = 20;
}

function mouseReleased() {
  val = 0;
}

Reflection

Overall, I am satisfied by the look of the project. I altered some CSS parameters to make the canvas corners rounded which gives a nice effect to the piece. Although we can intuitively realize that this is our solar system, I wished to add more detail to the planets. For example, Saturn’s rings and Earth’s life, i.e., greenery. Unfortunately, since I lost all of my progress and had to trace my steps in order to remake the piece, I was left with little time to try and achieve that. Although I could have created a Saturn class, I wanted to make use of OOP and use one class for all planets. I am very happy with the trail and glow effect I created by utilizing the alpha variable of fill. In the future, I wish to create pieces that are more artistic, perhaps expressionist, but since I am not used to combining art with OOP, I know it will take some time.

 

Homework 03 – Art with Classes, “The Satanic Donut”

Sketch

Concept

“The Satanic Donut” is a donut that tries to, but can never completely finish creating itself. One way to interpret it is as a display of never-ending conflict, due to its rapidly-moving and constantly-at-odds components of red and black colour.

As classes allow us to create objects where each object can have its own unique behaviour, I got the idea to create an art piece where the entities inside the art piece are the ones creating the art. Therefore, I conceptualised two groups of entities inside my art: ‘leaders’ and ‘followers’. The leaders move around, while the followers follow the leaders. All entities leave a trail of colour as they move around, as if there are many small brushes simultaneously creating the art piece.

The catch is, the leaders never stop moving towards their cryptic destination, while the followers never stop going after them. Thus, the art piece can never truly finish drawing itself.

Code highlight

A particularly interesting part of the code is the logic that enables each follower to ‘steer’ towards a leader. The followers don’t instantly turn in the direction of their target, but instead perform a smooth turn.

steerTowardsTarget() {
  // Update velocity to point towards the target.
  // However, use a 'steering' effect so the follower does not instantly turn
  // towards the target, but instead gradually turns.
  if (this.target == null) {
    return;
  }
  
  // v here is a vector pointing towards the target, with its magnitude being
  // how far we have to move.
  let v = this.target.pos.copy();
  v.sub(this.pos);
  
  if (v.mag() <= this.speed) {
    // We have reached the target.
    this.velocity = v.copy();
  } else {
    // Make v have a magnitude of our speed.
    // It is still pointing towards the target.
    v.normalize();
    v.mult(this.speed);
    // Make v be the vector from the tip of our current velocity
    // to the tip of the vector pointing towards the target.
    v.sub(this.velocity);
    // Multiply v by a constant to make its effect less pronounced.
    v.mult(STEERING_CONSTANT);
    // Add v to our velocity, to partially change velocity towards our target.
    this.velocity.add(v);
  }
}

The explanation for how this works requires a bit of math knowledge, but this video explains it very well, starting from 50:27. This is where I found out about this concept.

Reflection

The concept of an art piece drawing itself using several small brushes is very interesting and is worth exploring more deeply. Namely, one could devise many different classes of entities, each of which moves in its own unique way or pattern. With every small modification, just running the simulation could create something you never expect.

Assignment 3 – Empty Connections

The Concept

This artwork is meant to symbolize the empty connections in our lives. The colors all represent the uniqueness of these connections, but the nodes of the connection itself are empty.  If you keep clicking, the connections become more and more erratic, as they collide with each other and  increase in speed. Eventually, they all disappear. But, if you keep clicking long enough, the screen refreshes and shows a new array of particles

The Sketch

Link to the sketch: https://editor.p5js.org/mhh410/full/wTNviGHab

The nodes in the network are objects of the Particle class, with the following attributes. The connection between them is formed when the distance between the X and Y coordinates is less than 100. After that, the color of the line is determined through the Lerpcolor function, which gets the color associated with each particle, and draws the line that is a combination of the two colors.

The particles can also collide with each other, and this changes the direction they move in. If the initial randomized speed assigned to a particle is too low, and it is too far from other particles, then it may be stationary. The collide function will essentially switch the velocity of the two particles colliding.

There is a mousePressed function, that is responsible for doubling the speed for each particle whenever the mouse is pressed. There is also a mousePressCount variable. As the particles eventually escape the canvas, there needs to be a reset. The reset occurs after 20 presses, which I estimate that is sufficient for all the particles to disappear.


After 20 mouse presses, the canvas resets : all the particles from the particle array are popped, 40 new particles are formed, and the background is reset.

 

Improvements

I would like to use this as a template to be able to create images of some form, but currently I have no idea how to do that. Perhaps some way to transpose the outline of an image and represent the image as nodes from this piece to form complex artistic designs.

Assignment 2 – Creative Piece

Concept

Initially, I thought of making something with lines and creating some sort of an illusion. Then I remembered something I saw in Brooklyn’s Botanic Garden during my study away. It was a series of lights in lines converging into one single point. It looked amazing in the dark and I was really inspired by its pattern, so I thought of recreating it.

I feel like the pattern came out exactly as I wanted it to be, maybe even better because it changes color based on the position of the mouse. Once I was done with the lines, I made triangles to give a 3D effect so it seems like the pattern is inside a cube.

Implementation

I had to think quite a lot about where to place the lines and where to converge them to give the illusion effect. Especially since we had to implement the pattern using for loops, I had to think about where I had to place the “i” to change the position of the lines in the way I wanted.

The two main sections of my code are where I implemented the for loops for the changing-color lines and for the top and bottom triangle patterns.

The first one for the changing-color lines is below:

// creating a for loop for the changing line patterns on the left and right
// loops till the width in steps of 5, the steps define the spacing between the lines
for (let i = 0; i < width; i = i + 5) {
  
  // changing color patterns, increase mouseX for more red and increase mouseY for more green
  stroke(mouseX - random(255), mouseY - random(255), random(255));
  
  // dividing pattern into two halves (left side and right side) and making separate lines for each
  
  // left half
  line(0, i, mouseX, mouseY);
  
  // right half
  line(width, height - i, mouseX, mouseY);
}

I played around with the color-changing part until I was satisfied with the color combinations I achieved. The lines were made in two parts, the left half and the right half. This gave a triangle effect (two triangles on the left and right changing colors) without actually creating triangles. The starting points for the lines were changed using the for loop and the ending points were always the mouse position.

The second one for the top and bottom triangle patterns was done using the following for loop:

// making a for loop for white triangle patterns on top and bottom
for (let i = 0; i < width / 2; i = i + 10) {
  noFill()
  stroke(100)
  
  // one point on the top left half of the canvas, one point on the mouse position, and another one
  // on the top right half of the canvas
  triangle(i, 0, mouseX, mouseY, width - i, 0)
  
  // repeating procedure for triangles on the bottom half
  triangle(i, height, mouseX, mouseY, width - i, height)
}

I achieved this pattern by dividing the width into two halves (left and right sections) and then looping to make triangles from left to right. The converse was done from the right-to-left half as well. This gave me the white triangles that move based on the mouse position.
 

Reflection

I feel like I achieved exactly what I was going for in this assignment and the pattern turned out to look quite visually pleasing. I had the chance of showing it to my friends as well and getting their feedback and I subsequently added the triangle patterns on the top and bottom right after. Next time, I would like to use the mouseClicked() and keyPressed() functions to add even more user interactions.

 

Homework 2: Work of Art

For this assignment, our task was to create a simple artwork using for loops and our knowledge from previous classes.

Initially I filled the canvas with a grid of rectangles and circles in a static manner. To make this pattern, I used a double for loop to draw the shapes over the y-axis and then the x-axis.

Then to increase interactivity, I changed the width of the squares and the circles to change dynamically based on the position of my mouse. To do this. I used the dist function to compute the distance from the position of the mouse. I had to spend a lot of time on how should the function be linked to the shapes. I realized the solution was actually much simpler that what I was trying to do initially.

My solution in the start was only plain white shapes so the most challenging part of the pattern was adding color. I had to do a lot of research and trial and error to understand how could I change the color of where I am hovering on the canvas. For this purpose, I eventually reached at the solution of using a map function within the fill function to change the color of where I am hovering only.

I further wanted the canvas to change color continuously on its own as well alongside the hover, for which I added the hue variable after setting the colorMode from RGB to HSB. Integrating this feature, was a challenge to achieve because I was not working with the ‘mod %’ function in the start so kept running into errors.

Below is the canvas for my artwork:

Reflections:

The assignment was an exciting one to work with. I really wanted to work with interactivity and in particular the draw function after my assignment 1. I got to work very creatively to create this piece using different functions within the draw function which allowed me to add dynamically changing shapes and colors. As I had never before used some of these functions, most of my time was spent on understanding their use correctly and debugging them. In the future, I think it would be interesting to try changing the number of shapes on the screen dynamically as well.

Week-2_Aibar

 

In this assignment we had to use our previous knowledge gained in class along with for() and while() loops to create a simple work of art. I decided to go with the for() loop and create some type of symmetrical work of art with some additional features as ability to change the background color by clicking the mouse and moving animation. This artwork is composed of a grid of black dots connected by white lines, which move with an oscillating animation and are framed by a changing background color.

Concept

This artwork explores the concept of symmetry and movement. The grid of black dots represents order and stability, while the moving white lines create an element of motion and energy. The constantly changing background color further emphasizes the sense of dynamism and highlights the symmetry of the artwork.

My initial in-class work was static and did not contain any kind of additional features as background change and movement of lines.

Draft 1

Highlight of some code

To create the basis if the artwork I first used for loop to create some symmetrical grid using small rectangles. The below code depicts the code:

for (x = m; x <= width - m; x += m) {
    for (y = m; y <= height - m; y += m) {
      noStroke();
      rect(x - 1, y - 1, 3, 3);
      stroke(255, 100);

After creating the basis, I started to draw the lines connecting the rectangles from different coordinates. The lines move in a circular, oscillating pattern around the grid of black dots, creating an interesting visual effect. A highlight of some code that I am particularly proud of is this circular movement of lines in oscillating pattern utilizing  sin(frameCount / 20) * 20 and  cos(frameCount / 20) * 20.

// Symmetrical lines with animation
   line(x, y, width / 2 + sin(frameCount / 20) * 20, height / 2 + cos(frameCount / 20) * 20);
   line(x, y, width / 2 + sin(frameCount / 20) * 20, 0 + cos(frameCount / 20) * 20);
   line(x, y, 0 + sin(frameCount / 20) * 20, height / 2 + cos(frameCount / 20) * 20);
   line(x, y, width / 2 + sin(frameCount / 20) * 20, height + cos(frameCount / 20) * 20);
   line(x, y, width + sin(frameCount / 20) * 20, height / 2 + cos(frameCount / 20) * 20);

Reflection

After some reflection on my project I identified couple of ideas for future improvement. Future improvements to this artwork could involve adding more elements to the grid of black dots, such as circles and other shapes, as well as introducing more colors to the background and adjusting the speed and intensity of the lines animation. Additionally, it could be interesting to experiment with different musical styles and incorporate sound into the artwork to further emphasize the sense of motion.

Assignment 2: Creative Piece!

Concept

As part of the second assignment, for which the task was to produce a creative piece, something that caught my attention was the following image from COMPUTER GRAPHICS AND ART Aug1977.

Therefore, I decided to replicate that, but not only replicate a single instance, but make it interactive such that I can essentially see every single one of the types of squares. Starting off with a basic Mouse Movement in the in-class exercise, I built upon it to make it move periodically over a speed as an automated animation. When that was done, I moved forward with adding more colors and making it playful! If you press the RIGHT ARROW, LEFT ARROW, or the ‘a’ key, you can add specific colors!

The reason I made the animation squares move automatically in the manner seen below was to replicate the old ‘DVD’ behavior in Screen Savers of Old Televisions!

Embedded Canvas

The final production for my assignment is as follows:

Code

While the entire code is well commented, and very concise (linked below), one specific segment of it that I would like to share is the use of a single for loop with a map function to change the x and y directions of the animations. I started the usage of the map function to make the animation follow the mouse movement, however I later adapted it to be an automated sequence.

  // A loop to draw the different squares
  for (let i = 0; i<230; i=i+20)
  {   
      // Fill with the dark backgrounds in the pyramid style
      fill(i,i,i);
    
      // To add the different colors with the key presses, such that they are added in an incremental way
      // For the Red Color
      if (i==redColorCounter){
        fill(255,160,122)
      }
      // For the Blue Color
      if(i == blueColorCounter){
        fill(0, 0, 255);
      }
      // For the Yellow Color
      if(i == yellowColorCounter){
        fill(255, 255, 0);
      }
      
      // Changing xPosition and the yPosition of the squares
      xPos = i*(map(xInc, 250, 500, 1.0, 1.9))
      yPos = i*(map(yInc, 250, 500, 1.0, 1.9))
      rect(xPos,yPos, 500-(i*2))
  }
  // Make the colors 'climb' the different squares in the animation
  redColorCounter+=20;
  blueColorCounter+=20;
  yellowColorCounter+=20;
}

 

Improvements

As a future step, I really want to use a modular approach with functions and eliminate any and all duplications or repetitions of similar code pieces. One example would be the movement in the x & y directions by adding a function (which I tried but was not working the way I wanted it to!).

The full canvas is linked here.

HW2: Generative Loop Art

Motivation

The motivation behind this project was to create a simple generative artwork using the p5.js library. The goal was to combine elements of randomization, user interaction, and geometric shapes to create a unique and visually interesting piece.

Concept

The concept behind the artwork is a grid pattern of randomly colored rectangles and ellipses. The user can interact with the artwork by moving the mouse, causing the size of the shapes and the stroke weight of the outlines to change dynamically. This adds a layer of unpredictability to the artwork, making each viewing experience unique. Moving the mouse across the x axis changes the size of the shapes, while moving the mouse across the y axis, changes the strokewidth.

Process of Implementation

The process of implementing the generative art can be broken down into two primary steps:

Generating the grid pattern of shapes in the draw() function:

function draw() {
  // nested for loops to create a grid pattern
  for (let i = 0; i < width; i += s) { 
    for (let j = 0; j < height; j += s) {
      // randomize the color and shape of each square
      fill(random(255), random(255), random(255)); // randomly generate a color for each shape
      if (random(1) > 0.5) { // randomly choose between a rectangle or an ellipse
        rect(i, j, s, s); // draw a rectangle
      } else {
        ellipse(i + s / 2, j + s / 2, s, s); // draw an ellipse
      }
    }
  }
}

Implement the mouseMoved() function to add user interaction:

// function to change the size and stroke weight of the squares on mouse movement
function mouseMoved() {
  s = map(mouseX, 0, width, 10, 50); // map the size of the shapes to the x position of the mouse
  strokeW = map(mouseY, 0, height, 1, 10); // map the stroke weight to the y position of the mouse
  strokeWeight(strokeW); // update the stroke weight with the new mapped value
}

Challenges

One challenge in this project was understanding the map() function and how it works to map one range of values to another. It was important to understand the arguments passed to the map() function and how it affected the output.

Another challenge was getting the grid pattern of shapes to line up correctly, as the size of each shape needed to be adjusted to create a seamless grid.

Reflections

This project was a great opportunity to learn about generative art and how p5.js can be used to create unique and visually interesting pieces by using loops. By implementing randomization, user interaction, and geometric shapes, I was able to create a simple but impactful generative art piece.

Link to p5 sketch: https://editor.p5js.org/swostikpati/full/3W7yvJ3yo

Wallpaper using loops

function setup() {
  createCanvas(500, 400, WEBGL);

  
}

function draw() {
  background(0);
  
  
  //for rotation
  rotateX(frameCount * 0.01);
  rotateY(frameCount * 0.01);

  noFill();
  stroke(255);
  
  //draw series of boxies that follows mouse
  for (let i = 0; i < 100; i++) {
    for (let j = 0; j < 150; j += 10) {
      box(mouseX, mouseY, 150);
    }
  }

  box(mouseX, mouseY, 100);
  box(mouseY, mouseX, 200);

  for (let i = 5; i < 100; i += 10) {
    for (let j = 10; j < 150; j += 50) {
      box(i, j, i + j);
    }
  }

  rotateX(frameCount * 0.01);
  rotateZ(frameCount * 0.01);
  //draw circle at center
  fill(0)
  stroke(0)
  circle(0,0,20)
}