Week 3: Generative Artwork

For this week’s task, I wanted to make a representation of a mathematical rule using “bubbles”.  However, I quickly ran into lag issues. Originally, I wanted to create 100 objects, but the program started lagging at a much lower count. I ended up discarding the original idea and started experimenting with other features such as random motion and color.

The sketch lags at 5 objects.

The sketch is less laggy at 1 object.

The bubbles start at a random colors of 7 previously determined colors. They then transition and span through the rest of the colors with the help of lerpColor(). The motion of the bubbles is randomized through noise() and is mapped on the entire screen. The size of the bubbles is also randomized on a predetermined range.

Challenges/concerns:

My code is relatively simple but the program lags a lot. I’m not sure what causes this lag. My guess is repeatedly calling noise() is inefficient, but I’m not sure how to optimize it while retaining the randomness of motion and color for all objects.

Code:

Thing[] things;
int thingsCount;


void setup() {
  size(640, 480);
  
  thingsCount = 5;
  
  things = new Thing[thingsCount];
  for (int i=0; i<things.length; i++) {
    things[i] = new Thing(random(0,width), random(0,height));
  }
}

void draw() {
  background(0);
  
  for (int i = 0; i<things.length; i++){
    things[i].display(); 
  }
}
class Thing {
  float x, y;
  float diameter;
  float tx, ty;
  float colorStage;
  int color1, color2, currColor;
  color[] palette;
  int colorFrequency;

  Thing(float xPos, float yPos) {
    x = xPos;
    y = yPos;
    diameter = random(70, 150);
    tx=random(0, 10000);
    ty=random(0, 10000);
    colorStage = 0;
    palette = new color[]{color(246, 0, 0), color(255, 140, 0), color(255, 238, 0), color(77, 233, 76), color(55, 131, 255), color(72, 21, 170)};
    currColor = int(random(0, 6));
    colorFrequency = 10;
  }

  void motion() {
    x = map(noise(tx), 0, 1, 0, width);
    y = map(noise(ty), 0, 1, 0, height);
    tx += 0.04;
    ty += 0.04;
  }

  color updateColor() {
    colorStage = (colorStage+colorFrequency) % 100;
    if (colorStage == 0) {
      currColor++;
    }
    currColor = currColor % palette.length;
    color1 = palette[currColor];
    if (currColor + 1 >= palette.length) {
      color2 = palette[0];
    } else {
      color2 = palette[currColor+1];
    }

    return lerpColor(color1, color2, colorStage/100);
  }

  void display() {
    color fillColor = updateColor();
    fill(fillColor);
    motion();
    stroke(255);
    ellipse(x, y, diameter, diameter);
    filter(BLUR, 8);
  }
}

 

Week 2: Loops

For the second week’s task, I wanted to use lines and circles to make some kind of pattern of motion. After adding lines, I quickly realized that adding circles would crowd the screen and be too overwhelming, so I decided to stick with lines only and develop them a bit further. My final sketch is displayed in the video below:

Challenges:

I faced two main challenges.

The first one relates to the motion of the lines. After adding the set of lines on the left, I was stuck on the set of the lines on the right. The amount of variables involved confused me, and I was unable to figure out how to set the motion of this set to be opposite to the other one. After tweaking the variables and trying to introduce new ones, I solved the issue by drawing a rough sketch of the lines on my phone and marking different parts of it, defining the variable which controls it.

The second challenge I faced related to the coloring of the sketch. I wanted to make the color of the lines’ stroke to change over time. I tried using random() and noise() to introduce random colors smoothly. However, it was difficult to make the color change smooth after experimenting with many numbers. I think the difficulty resulted from the fact that three parameters control the resulting RGB color. I tried looking up how to use Hex colors, but that was difficult to implement as well. So I just decided to go with a lighter shade of gray

Decision-making:

I wanted the lines to rotate and after some time reverse and rotate the other way. I used frameCount at first, but I realized it was difficult to utilize since I wanted a variable that decreases after a certain amount of time. At the end, I decided to make my own variable that increases and decreases.

Code:

int counter;
float speed;
boolean increaseCounter;

void setup() {
  size(640, 480);
  
  counter = 0;
  speed = 0.007;
  increaseCounter = true;
}

void draw() {
  background(0);
  
  stroke(200);
  if ((counter+1) * speed >= radians(90)) {
      increaseCounter = false;
    } else if (counter <= 0) {
      increaseCounter = true;
    }
    if (increaseCounter) {
      counter++;
    } else {
      counter--;
    }
  
  for (int i = 20; i <= width; i += 40) {
    float frequency = (counter * speed);
    pushMatrix();
    translate(i, i);
    strokeWeight(1.5);
    rotate(frequency);
    line(-i, 0, width-i, 0);
    popMatrix();
  }
  
  for (int i = width; i >= 0; i -= 40) {
    float frequency = (counter * speed);
    pushMatrix();
    translate(i, width-i);
    strokeWeight(1.5);
    rotate(-frequency);
    line(-i, 0, width-i, 0);
    popMatrix();
  }
}

 

Week 1: Self-Portrait

This is my submission for the first week’s task. I decided to replicate a sketch since I wasn’t sure how to design a distinctive self-portrait.

Inspiration:

The character depicted in my submission is inspired by a sketch I drew a few months ago:The most significant change I made compared to this sketch is the hat I added mainly because hair design was difficult/ineffective. The character is named “Sketch Dude”, and he hates it when people invade his private Zoom box space.

Code:

I used a variety of shapes to design this character. I used lines, ellipses, arcs, bezier curves, and a rectangle. I hardcoded most of the design since my design is not symmetrical and keeping track of the variables would be difficult. However, I used global variables to design the interactive part of the program. I wrote three methods/functions to define the interactive parts of the program (Zoom box, eyes, mouth). Whenever the pointer goes into the Zoom box, the character becomes mad. As the pointer moves out of the Zoom box, the character becomes less mad and returns to his normal state. Following are sample pictures, a video, and the code of the project:

int zoomBoxWidth, zoomBoxHeight, nameTagW, nameTagH, eyeSize, eyeSizeMin, eyeSizeMax;

boolean isInBox() {
  if (mouseX >= width/2 - zoomBoxWidth/2 && mouseX <= width/2 + zoomBoxWidth/2 && mouseY >= height/2 - zoomBoxHeight/2 && mouseY <= height/2 + zoomBoxHeight/2) {
    return true;
  } else {
    return false;
  }
}

void eyes() {
  rotate(2*PI - 0.22);
  noStroke();
  if (isInBox() && eyeSize <= eyeSizeMax) {
    eyeSize++;
  } else if (!isInBox() && eyeSize >= eyeSizeMin) {
    eyeSize--;
  }
  if (eyeSize > eyeSizeMin) {
    fill(255, 0, 0);
  } else {
    fill(0);
  }
  circle(width/2 - 55, height/2 - 41, eyeSize);
  circle(width/2 - 2, height/2 - 42, eyeSize);
}

void mouth() {
  noFill();
  stroke(0);
  strokeWeight(5);
  if (isInBox()) {
    strokeJoin(MITER);
    beginShape();
    vertex(267, 264);
    vertex(282, 246);
    vertex(302, 260);
    endShape();
  } else {
    line(266, 257, 305, 253);
  }
}

void setup(){
  size(640, 480);
  zoomBoxWidth = 440;
  zoomBoxHeight = 330;
  nameTagW = 90;
  nameTagH = 20;
  eyeSizeMin = 13;
  eyeSizeMax = 33;
  eyeSize = eyeSizeMin;
}

void draw(){
  background(150);
  
  //zoom box
  noStroke();
  fill(0, 50);
  rect(width/2 - zoomBoxWidth/2, height/2 - zoomBoxHeight/2, zoomBoxWidth, zoomBoxHeight);
  fill(0, 150);
  rect(width/2 - zoomBoxWidth/2, height/2 + zoomBoxHeight/2 - nameTagH, nameTagW, nameTagH);
  fill(255);
  text("Sketch Dude", width/2 - zoomBoxWidth/2 + 5, height/2 + zoomBoxHeight/2 - 5);
  
  //face
  stroke(0);
  strokeWeight(3);
  noFill();
  arc(width/2 - 30, height/2 - 30, 100, 170, HALF_PI + QUARTER_PI, PI + QUARTER_PI);
  arc(width/2 - 49, height/2 + 48, 40, 50, HALF_PI  + QUARTER_PI, PI + QUARTER_PI);
  arc(width/2 - 49, height/2 + 64, 30, 30, PI, 2 * PI);
  line(286, 303, 303, 276);
  line(303, 276, 353, 255);
  line(254, 149, 256, 135);
  arc(width/2 - 30, height/2 - 30, 100, 170, HALF_PI + QUARTER_PI, PI + QUARTER_PI);
  
  //body
  noFill();
  strokeWeight(3);
  arc(width/2 - 10, height/2 + 70, 10, 70, PI + HALF_PI, 2*PI + QUARTER_PI);
  
  strokeWeight(5);
  bezier(314, 324, 226, 330, 225, 335, 210, 480);
  line(260, 480, 268, 400);
  arc(width/2 + 20, height/2 + 85, 90, 70, 0, PI);
  line(400, 480, 400, 400);
  bezier(386, 324, 442, 329, 445, 333, 465, 480);
  line(400, 400, 410, 480);
  
  strokeWeight(4);
  rect(width/2 + 25, height/2 + 165, 40, 40, 0, 0, 10, 10);
  
  //hair
  strokeWeight(6);
  arc(width/2 - 19, height/2 + 10, 130, 300, PI + QUARTER_PI, 2*PI + QUARTER_PI);
  arc(width/2 - 10, height/2 + 10, 130, 300, PI + QUARTER_PI, 2*PI + QUARTER_PI);
  arc(width/2 - 1, height/2 + 10, 130, 300, PI + QUARTER_PI, 2*PI + QUARTER_PI);
  arc(width/2 + 8, height/2 + 10, 130, 300, PI + QUARTER_PI, 2*PI + QUARTER_PI);
  arc(width/2 - 5, height/2 + 5, 80, 300, PI + HALF_PI, 2*PI + QUARTER_PI);
  arc(width/2 + 10, height/2 + 5, 80, 300, PI + HALF_PI, 2*PI + QUARTER_PI);
  arc(width/2 + 19, height/2 + 5, 80, 300, PI + HALF_PI, 2*PI + QUARTER_PI);
  arc(width/2 + 28, height/2 + 5, 80, 300, PI + HALF_PI, 2*PI + QUARTER_PI);
  arc(width/2 + 37, height/2 + 5, 80, 300, PI + HALF_PI, 2*PI + QUARTER_PI);
  
  //hat
  stroke(255);
  strokeWeight(2);
  fill(0);
  arc(width/2 + 5, height/2 -80, 150, 150, PI + 0.3, 2*PI + 0.2, CHORD);
  rotate(0.22);
  rect(width/2 - 50, height/2 -170, 165, 38, 5);
  
  //eyes
  eyes();
  
  //nose and mouth
  stroke(0);
  strokeWeight(5);
  line(275, 232, 290, 230);
  mouth();
    
}