Week 3: Generative Art using OOP


For this assignment, I was inspired by the piece we looked in class by Manfred Mohr, titled “space.color.motion”, that showed the projection of higher dimension object in 2D.Link to the artwork: space.color.motion

I did not implement any mathematical functions, simply because I am not aware of them, but I tried mimicking the actions of the shape. It did turn out to be completely different, but the properties of the shapes are somewhat retained in my approach like the overlapping of shapes onto the other and the change in shape. Some properties I added in was the varying opacity of the shape color and the rotation of the shapes.


As part of the requirement for the assignment, I used a class called Shape which has parameters that represent four points for a quadrilateral. These points are random and create a random quadrilateral on the canvas. The display() function creates the quadrilateral and fills in a random color and a random stroke weight to the shape. The color has varying opacity, which I implemented through the .setAlpha in-built function for color. Finally, the rotate_() function rotates the shape with the axis of rotation at position (0, 0).

class Shape {
  constructor() {
    // the shape is a quadrilateral, so require four points.
    // these points are random and one is in the range of 'vary' with respect to one another.
    this.x1 = random(width);
    this.y1 = random(height);
    this.x2 = random(this.x1 - vary, this.x1 + vary);
    this.y2 = random(this.y1 - vary, this.y1 + vary);
    this.x3 = random(this.x2 - vary, this.x2 + vary);
    this.y3 = random(this.y2 - vary, this.y2 + vary);
    this.x4 = random(this.x3 - vary, this.x3 + vary);
    this.y4 = random(this.y3 - vary, this.y3 + vary);
    // random color for the shape.
    this.clr = color(random(255), random(255), random(255));
    // random stroke weight for the shape
    this.strWeight = random(2, 7);
    // changes the opacity of the shape to a random value. Gives a glass-like illusion to the shape
  display() {
    // Creating a quadrilateral.
    quad(this.x1, this.y1, this.x2, this.y2, this.x3, this.y3, this.x4, this.y4);
  rotate_() {
    // stops the rotation when the mouse is clicked as the angle becomes constant
    if (!mouseIsPressed) {


I tried to mimic the movement of the edges as in the original, but it proved to be very difficult. I smoothened the movement with the use of noise, and rotated the objects so that we get varied shapes and images.

Notice that the rotate_() function rotates the objects only if the mouse is not pressed. If we press the mouse, the shapes stop rotating and start jittering. The shape changes its shape randomly. This random movement comes from the combination of noise and random functions with a change in the sign of the movement. If the sign is negative, the points would move left or up, and if the sign is positive, the points would move right or down. However, this movement is restricted to certain extent, such that the shapes do not move too far away from the visible part of the canvas. This was implemented with the following limit_point function.

function limit_point(i) {
    // limits the movement of the point. It keeps the shape with in a random range of 100 to 200 pixels of the canvas. In other words, it does not let the corners of the shape go beyond the canvas width or height plus some pixels in the range 100 to 200.
    if ((shapes[i].x1 > width + random(100, 200)) || (shapes[i].x1 < 0  - random(100, 200))) {
      sign_x1 *= (-1);
    if ((shapes[i].y1 > height + random(100, 200)) || (shapes[i].y1 < 0 - random(100, 200))) {
      sign_y1 *= (-1);
    // does the same random movement for another point/corner of the shape
    shapes[i].x2 += noise(random(-jitter+93, jitter+88)) * sign_x2;
    shapes[i].y2 += noise(random(-jitter+10, jitter)) * sign_x2;
    if ((shapes[i].x1 > width + random(100, 200)) || (shapes[i].x2 < 0 - random(100, 200))) {
      sign_x2 *= (-1);
    if ((shapes[i].y1 > height + random(100, 200)) || (shapes[i].y2 < 0 - random(100, 200))) {
      sign_y2 *= (-1);
    // does the same random movement for another point/corner of the shape
    shapes[i].x3 += noise(random(-jitter+89, jitter+23)) * sign_x3;
    shapes[i].y3 += noise(random(-jitter+45, jitter+48)) * sign_y3;
    if ((shapes[i].x1 > width + random(100, 200)) || (shapes[i].x3 < 0 - random(100, 200))) {
      sign_x3 *= (-1);
    if ((shapes[i].y1 > height + random(100, 200)) || (shapes[i].y3 < 0 - random(100, 200))) {
      sign_y3 *= (-1);
    // does the same random movement for another point/corner of the shape
    shapes[i].x4 += noise(random(-jitter+5, jitter+88)) * sign_x4;
    shapes[i].y4 += noise(random(-jitter+76, jitter+34)) * sign_y4;
    if ((shapes[i].x1 > width + random(100, 200)) || (shapes[i].x4 < 0 - random(100, 200))) {
      sign_x4 *= (-1);
    if ((shapes[i].y1 > height + random(100, 200)) || (shapes[i].y4 < 0 - random(100, 200))) {
      sign_y4 *= (-1);

This function takes in the index of the shapes array as an argument and limits the points of a quadrilateral with in a random range of 100 to 200 pixels from the edges of the canvas.

The draw function then simply runs all the functions on the shapes created in the setup function.

function draw() {
  for (let i = 0; i < shapes.length; i++) {
    // displays all the shapes
    // rotates all the shape with respect to (0,0)
    // limit the movement of the points of a shape

The background was chosen such that the shapes would pop out and as an aesthetic measure. As part of the interactivity in the project, I added the functionality of adding new shape whenever a mouse click is registered. The shape created has a random position and might not be visible on the canvas right away but is created and is visible when the canvas rotates.

function mouseClicked() {
  // creating a new shape when the mouse is clicked
  shapes[shapes.length] = new Shape();

Further improvements

While I was trying to rotate the objects, I tried to rotate them such that all the shapes rotated with a different axis. However, the implementation using the push() and pop() function did not work as expected. This could be one of the improvements I could make in the future.

The inspiration for the project had very smooth movements, while mine is not as smooth. I could work on the smoothness as well.

Leave a Reply