Flower Text – Jade

 

Description 

In this project, I referred to some works of Professor Aaron and added some ideas. The project is about various flowers of different colors made up by texts.

For the interaction part, if you press “W”, a new flower will be added at mouse coordinate, and if you press “S”, a random flower will be deleted. Pressing “R” will restart the program. There are two modes designed in the program. By default, when you put the cursor around the texts, they move away. Clicking the mouse will change the mode. In this mode, the texts will randomly move around.

 

Code

Mover is the foundation class of my program, which I referred to Professor Aaron’s text example and modified some parts. Every alphabet of a string  is a Mover.The Mover class includes the physical attributes like speed, acceleration and gravity.

class Mover{
  PVector velocity;
  PVector gravity;
  PVector position;
  PVector acceleration;
  PVector wind;
  float drag;
  float mass;
  float hDampening;
  PVector speed;
  
  Mover(PVector pos, float _mass, PVector _speed){
    mass=_mass;
    position = pos;
    speed = _speed;
    velocity = new PVector(0,0);
    acceleration = new PVector(0,0);
    gravity = new PVector(0, 0.1*mass);
    drag = map(mass,15, 80, .999, .96);
    wind = new PVector(0,0);
    set_hDampening();
  }

  void move() {
    position.add(speed);
    speed.x *= 0.98;
    speed.y *= 0.98;
    acc = new PVector(0, 0);
    bounds();
  }
  
  void update(){
    wind.x=globalWind1;
    wind.y=globalWind2;
    if (globalWind1==0)
    velocity.x*=hDampening;
    applyForce(wind);
    applyForce(gravity);
    velocity.add(acceleration);
    velocity.mult(drag);
    position.add(velocity);
    bounds();
    acceleration.mult(0);
  }
  
  void display(){
    ellipse(position.x,position.y,mass,mass);
  }
  
  void bounds(){
    if (position.x>width - 30)
      position.x=width - 30;
    if (position.x<0)
     position.x=0;
    if (position.y>height)
      position.y=height;
    if (position.y<45)
      position.y=45;
  }
  
  void set_hDampening(){
    hDampening=map(mass,0,100,.98,.96);
  }
  
  void applyForce(PVector force){
    PVector f = PVector.div(force, mass);
    acceleration.add(f);
  }
  

}

The Letter class prints out the Movers.

class Letter extends Mover{
  char let;
  Letter(PVector pos, float _mass, char s, PVector _speed){
    super(pos,_mass, _speed);
    let=s;
    drag = random(.98,.999);
  }
  
  void display(){
    text(let,position.x,position.y);
  }
 
}

 

The most significant part of my project is the Flower class, which transforms letters into flowers.  It basically concatenates the letters to form a circle and adds animations to the letters. The run function is for shifting between the two modes, and the generate function is for changing colors.

class Flower {
  float x, y;
  String s;
  PVector speed = new PVector(0,0);
  ArrayList<Letter> letters = new ArrayList<Letter>();
  
  Flower(String _s, float _x, float _y) {
    s = _s;
    x = _x;
    y = _y;
  }
  
  void show() {
    generate();
    run();
  }
 
  void mysetup() {
    for (int i=0; i<s.length(); i++) {
      char c = s.charAt(i);
      float radius = random(s.length()*15, s.length()*25);
      float angle = PI + i*TWO_PI/s.length();
      float posx = cos(angle)*radius + x;
      float posy = sin(angle)*radius + y;
      PVector pos = new PVector(posx, posy);
      letters.add(new Letter(pos, random(0.1, 0.3), c, speed));
    }
  }
  
  
  void mouse_pos(Mover object) {
    float x = object.position.x;
    float y = object.position.y;
    if (dist(mouseX, mouseY, x, y)<30) {
      acc = new PVector(cos(random(TWO_PI)), 
      cos(random(TWO_PI)));
      speed.add(acc);
    }
  }
  
  
  void run() {
    if (bool) {
      for (int i=0; i<s.length(); i++) {
        mouse_pos(letters.get(i));
        letters.get(i).move();
        letters.get(i).display();
      }
    }
  
    if (!bool) {
      for (int i=0; i<s.length(); i++) {
        globalWind1 = random(-0.3, 0.3);
        globalWind2 = random(-0.35, 0.3);
        letters.get(i).update();
        letters.get(i).display();
      }
    }
  }
    
  void generate() {
    switch (s) {
    case "Rose":
      fill(#D8163A);
      break;
    case "Dandelion":
      fill(255);
      break;
    case "Sunflower":
      fill(#EFF70A);
      break;
    case "Daisy":
      fill(#E3A3E2);
      break;
    case "Carnation":
      fill(#F083E5);
      break;
    case "Iris":
      fill(#B44EB4);
      break;
    }
    mysetup();
  }
  
}

 

Below is my main function where I put parameters into the flower class, and design the interactions.

PFont f;
String s;
String [] words = {"Rose", "Dandelion", "Sunflower", "Daisy", "Carnation", "Iris"};
Flower flower;
ArrayList<Flower> flowers = new ArrayList<Flower>();
int count = 0;

float globalWind1=0;
float globalWind2=0;
PVector acc = new PVector(0,0);
boolean bool = true;

void setup() {
  size(600, 600);
  f = createFont("Monaco", 60);
  textFont(f);
  s = words[0];
  flower = new Flower(s, width/2-(textWidth(s)/2), height/2);
  flowers.add(flower);
  count += 1;
}


void draw() {
  background(#EDE5FF);
  for (int i = 0; i < flowers.size(); i++) {
    flower = flowers.get(i);
    flower.show();
  }
  if (!keyPressed)
    globalWind1=0;
    globalWind2=0;
}


void keyPressed() {
  if (key == 'r' || key == 'R') {
      while (count > 0) {
        delete_flower();
     }
   }
   
  //if (keyCode==LEFT) {
  //  globalWind1=-0.3;
  //}
  //if (keyCode==RIGHT) {
  //  globalWind1=0.3;
  //}

  //if (keyCode==UP) {
  //  globalWind2=-0.5;
  //}
  //if (keyCode==DOWN) {
  //  globalWind2=0.5;
  //}
  
  if (key == 'w' || key == 'W') {
    add_flower();
  }
  if (key == 's' || key == 'S') {
    delete_flower();
  }
}

void mouseClicked() {
  bool = !bool;
}

void add_flower() {
  s = words[count % 6];
  flower = new Flower(s, mouseX, mouseY);
  flowers.add(flower);
  count += 1;
}

void delete_flower() {
  try {
    flowers.remove(int(random(0, 6)));
    count -= 1;
  } catch (Exception e) {  
  }
}

 

Challenges 

This project is pretty challenging as I have three classes connected with each other. It’s hard to organize these classes. Adding new features and animations can be painful because I have to also modify the classes, and it requires a clear mind and efforts. You can easily get an error message for not sorting things out.

For example, when I was trying to make alphabets randomly move by adding a variable globalWind to the Mover class, I encountered a problem that every alphabet moves towards the exactly same directions. My final solution was to add a speed parameter to flower class.

There is still a problem I haven’t solved. When I was trying to change the font, the intervals between alphabets are not evenly distributed. So some alphabets appear too close, but some are far away from each other. I don’t understand why — I think it should be displayed normally because my code was to calculate textWidth before locating the positions.

Overall, I think making this project improves my understanding of classes, especially how the parameters can help. It also helps me get grasp of the physics in Processing.

Hope you enjoy  🙂

 

Ocean Currents (Generative Art) – Jade

 

Description

This work was inspired by an artwork I saw on Youtube. I love the flowing lines, the dynamic movements, and the way it interacts with people.

In this work, I used the concepts of Object-Oriented Programming and the particle system. My favorite part of this project is the interaction with the cursor, that changes both the transparency of the background and the starting point of the particles. Also I added the two perpendicular lines to locate the cursor and to show how the particles change with the move of my mouse.

 

Code

This part is my class of the particles.

 class Particle {               
  float posX, posY, val=0, angle, speed=2;   
  color c;    
  float r, g, b;
    
  Particle() { 
    posX = random(width);
    posY = random(height);
  }
 
  // the main function of the class
  void run() { 
    update();
    add_color();
    check();
    generate();
  }
 
  // update the position of particles
  void update() {     
    float noise_val = noise(posX * 0.005, posY * 0.004, val);    
    val += 0.01;  
    angle = noise_val * TWO_PI;
    
    posX += speed * cos(angle);  
    posY += speed * sin(angle);
    
  }
  
  // when particles in the canvas, draw the particles
  void generate() {
    if (posX > 0 && posX < width && posY > 0  && posY < height) {
        lines();
        ellipse(posX, posY, 2, 2);
    }
  }
  
  // check if the particles are out of edges, so to place them back to the canvas
  void check() {   
    if (posX< 0 || posX > width) 
      posX = mouseX;
    if (posY < 0 || posY > height)
      posY = mouseY;
  }
  

  // generate slightly different blue colors
  void add_color() {
      float col = map(posY, 0, height, 255, 0); 
      c = color(30, col, 255); 
      fill(c);
  }
  
  // the lines intersecting at mouse coordinates
  void lines() {
     stroke(150, 150, 150);
     line(mouseX, 0, mouseX, height);
     line(0, mouseY, width, mouseY);
  }

}

The part below is my main function.

Particle[] particles;     
float trans;     
int nums = 500;
 
void setup() {
  size(300, 600);
  background(#070B46);
  noStroke();
  setParticles();         
}
 
void draw() {
  trans = map(mouseY, 0, width, 0, 50);  // transparency changes with mouseY
  fill(#070B46, trans);  // background    
  rect(0, 0, width, height);
  for (int i = 0; i < nums; i++) {
      particles[i].run();
  }
}
 
// make the particles
void setParticles() {        
  particles = new Particle[nums];  
  for (int i = 0; i < nums; i++) {        
    particles[i]= new Particle();   
  }
 
}-
 
// if pressed, regenerate all the particles
void mousePressed() {
  setParticles();
}

 

Process

I set the canvas to be size(300, 600) because I think this size fits the patterns best, and I think I want to create a bottle-like scene. When running this project, it first randomly generates 500 particles across the canvas. When you move the cursor up and down, it changes the transparency of the background, which results in the change of the density of the particles visually. As the particles strike the edges, new particles will generate at either (x, mouseY) or (mouseX, y). To be visually clearer, I added the two lines to better display where the particles appear, which turns out to be pretty cool. Since quite a few parameters are related to mouseX and mouseY, as you move the cursor around, it may create some artistic patterns and effects. Pressing mouse would regenerate the particles randomly, in other words, refresh the work.

One of the difficulties I encounter was to adjust the parameters of the particles, like their color, speed and angles. It takes time to experiment to achieve my expectation. I initially wanted to make the color change every time the particles are regenerated. So I included the code for color in the void generate() function, but it didn’t work out and only filled in the same color. After a few attempts, the approach I eventually take is to use the map function to make the color change with my mouseY.

The most challenging part is about the class/ struct. After writing different functions, I found it sometimes confusing when putting them together, especially when I wanted to use functions inside another function. As result, I also found it challenging to decide whether this function should be put in draw function or the setup function.

 

Conclusion

I think this project really improves my understanding of class and noise/map functions. And it is always interesting and surprising to see what will come out as I change the parameters. I feel that randomness is really an important part of Processing artworks. Randomness inspires me and leads me during the whole time.

Assignment Week 2 – Jade

Documentation:

For this assignment, I used sin, cos, radians, map and for loop functions to make up waves to simulate texture of clothes. I referred to this website for the basics of waves.

The most challenging part is to imagine what the outcome would be like when entering parameters for the map function, so I kept trying different values to achieve what I expect. I actually didn’t have a blueprint in my mind at first, instead, I was inspired as I adjusted the parameters. As I changed the rate of “frameCount” and the index “I”, the small rectangles started to gradually make up specific patterns.

The up-left corner of my work came out unexpectedly, but it caught my eyes for its regularity. At the beginning, it looks like this:

It moves like it’s knitting and sewing, so I thought that I can try to make patterns of textures. The first problem I encountered is that as the white rectangles move, they started to pile up, and eventually covered the entire screen, so it became all white after some time. To solve this, I introduced waves into color setting, where I wrote this line of code:

float color1 = map(cos(radians(frameCount)*5), -1, 1, 0, 255);

This line basically changes the color every time the draw function runs, so that they will never be able to fill the entire screen, but gradually changes.

But one pattern still seems too simple, so I decided to add more with different styles. I set the size to be (500, 500) to hold four patterns regularly.

The up-right corner is almost the same pattern with the left one in a different color, but I found it interesting that the waves of lines are harmonically connected. For the two textures below, I combined different parameters and they are knitting and moving in different ways. The left bottom one is like it is printed out, and the right bottom is made up of numerous dots. It takes some time for these two to form the final patterns.

Finally, I set them all to share the similar speed so that they can synchronize with each other as the pattern changes.

For my simple work of art, I chose to display textures of clothes in a dynamic way. For me, usually I pay more attention to the patterns and designs of clothes, not the textures, but texture is actually the most basic and significant element of clothes.

void setup() {
  size(500, 500);
  background(0);
}

void draw() {
  noStroke();
  for (int i=0; i<80; i++) {

    float wave1 = map(sin(radians(frameCount * 0.8 + i)), -1, 1, -100, 500);
    float wave2 = map(cos(radians(frameCount + 10*i)), -1, 1, -100, 500);
    float color1 = map(cos(radians(frameCount)*5), -1, 1, 0, 255);
    fill(color1);
    if (wave1 > 0 && wave1 < 250 && wave2 > 0 && wave2 < 250) {   
      rect(wave1, wave2, 6, 8);
    }
    
    
    float wave11 = map(sin(radians(frameCount * 0.8 + i)), -1, 1, -100, 500);
    float wave22 = map(cos(radians(frameCount)+i), -1, 1, -100, 500);
    float color2 = map(cos(radians(frameCount)*2), -1, 1, 0, 100);
    fill(color2);
    if (wave11 > 250 && wave11 < 500 && wave22 > 0 && wave22 < 250) {   
      rect(wave11, wave22, 5, 5);
    }
    
    
    float my_color1 = map(cos(frameCount * 2), -1, 1, 0, 255);
    float x = map(sin(frameCount * 0.8 + i), -1, 1, -100, 500);
    float y = map(cos(frameCount - 10 * i), -1, 1, -100, 500);
    fill(my_color1);
    if (y > 250 && y < 500 && x > 250 && x < 500) {
    rect(x, y, 2, 2);
    }
    
    float my_color2 = map(sin(frameCount * 10), -1, 1, 0, 255);
    float x1 = map(sin(radians(frameCount * 0.9)), -1, 1, -100, 500);
    float y1 = map(cos(radians(frameCount * i)), -1, 1, -100, 500);
    fill(my_color2);
    if (y1 > 250 && y1 < 500 && x1 > 0 && x1 < 250) {
    rect(x1, y1, 3, 3);
    }
  }
}

 

Self Portrait – Jade

WEEK 1 Documentation

 

In this project, I used some basic functions of Processing and shapes like lines, quads, ellipses, triangles and rectangles to make a self-portrait. I also included a little animation using knowledge learned from class. I intended to portrait my face in an angle, so in my project, my face has turned right a little bit.

Throughout the whole process, I faced some difficulties, like appropriately locating the points. I had to adjust the coordinates several times so that they can finally make up the shape I want. And when I was doing the animation of my mouth, it was strange that as my mouth moved, there appeared a black triangle, so I had to place a rectangle of the background color behind my mouth triangle. That’s why I have this line of code:

rect(width/2 - 60, height/2 + 50, 100, 70);

However, among all the difficulties, I found depicting my hair most challenging. I first tried to use curves and the BezierVertex, but unfortunately since I didn’t master these functions, it didn’t go well. So then I used arcs, and to make it more me, I added some quads at the back.

From this project, I think I have learned and improved a lot as I tried using various functions and shapes in Processing. Although my work might not be artistic or elaborate, I think it captured some of my features. I am sure that I still have got a lot to learn in Processing since I kept coding in a stupid way, and I look forward to learning more of it!

 

My Code:

int mouth_height = 50;
int speed = 1;
PFont f;


void setup() {
  size(640, 480);
  background(#FFFFAD);
  
  // hair
  noStroke();
  fill(#4B2D0E);
  quad(286, 100, 243, 60, 181, 122, 188, 264);
  quad(398, 110, 454, 95, 460, 283, 300, 283);

  // head
  stroke(0);
  strokeWeight(2);
  fill(249, 236, 228);
  ellipse(width/2, height/2 - 10, 270, 300); 
  quad(269, 360, 274, 433, 422, 440, 401, 360);
  noStroke();
  rect(268, 353, 120, 15);
  fill(255);
  stroke(0);
  quad(252, 400, 281, 450, 322, 435, 296, 415);
  triangle(322, 435, 425, 400, 425, 460);
  
  // eyebrow
  noStroke();
  fill(#4B2D0E);
  triangle(227, 156, 220, 145, 290, 156);
  triangle(329, 152, 378, 140, 390, 153);
  
  // front hair
  noStroke();
  fill(#4B2D0E);
  arc(260, 109, 160, 130, radians(135), radians(315));
  arc(356, 110, 200, 180, radians(200), radians(360+45));
  
  // eyes
  stroke(0);
  fill(255);
  ellipse(240, 180, 70, 30); 
  ellipse(370, 180, 80, 30); 
  
  fill(#461414);
  ellipse(240, 180, 30, 30);
  ellipse(370, 180, 40, 30);

  fill(255);
  ellipse(236, 183, 7, 7);
  ellipse(364, 182, 7, 7);
  

  // nose
  fill(0);
  strokeWeight(2);
  line(width/2 - 20, height/2 - 40, width/2 - 35, height/2 + 10);
  line(width/2 - 10, height/2, width/2, height/2 + 10);
  line(width/2 - 35, height/2 + 10, 298, 256);


  // glasses
  fill(206, 209, 227, 118);
  stroke(#F2E662);
  rect(180, 140, 110, 80, 12, 24, 48, 72);
  line(290, 180, 320, 180);
  rect(320, 142, 115, 80, 12, 24, 48, 72);
  line(435, 180, 450, 160);

  // ear
  stroke(0);
  fill(249, 236, 228);
  arc(455, 229, 35, 50, TWO_PI - HALF_PI, TWO_PI + HALF_PI);
  

  // sign
  f = createFont("AmericanTypewriter-Semibold", 48, true);
}

void draw() {
  println(mouseX + ", " + mouseY);

  // mouth
  fill(249, 236, 228);
  noStroke();
  rect(width/2 - 60, height/2 + 50, 100, 70);
  
  if (mouth_height == 80 || (mouth_height == 50 && speed < 0)) {
    speed *= -1;
  }
  
  mouth_height += speed;
  fill(#FFD3D3);
  stroke(0);
  strokeWeight(2);
  triangle(width/2 - 40, height/2 + 50, width/2 + 30, height/2 + 50, width/2 - 30, height/2 + mouth_height);

  fill(0);
  textFont(f, 30);
  text("Jade Zhou", 480, 389);
}

 

My work: