Assignment 1. Self-Portrait

For my first assignment, I decided to start with the basic shapes to make sure that I was comfortable with the foundations. I did not want to be too meticulous about the details; rather, I used my imagination and spatial thinking to draw fun yet precise face features that would properly display what game/social media avatars usually do.

Basic shapes – the avatar itself.

In the first stage of my work, I created a head, eyes, eyeballs, ears, and nose using straightforward ellipse() and circle() commands. I searched the Web for the most real-looking skin color RGB code and used it.

The next step was to find out the way to draw mouth, eyebrows, and hair. Again, I wanted my sketch to be similar to the real person’s features, so I decided to spend more time searching for proper code options. Looking at the examples from the past students’ work and watching the videos from The Coding Train helped me to get the idea of using arc() and quad() functions. The lesson that I learned from using these two functions is that you should be very precise with values and pay attention to details, otherwise you might mess up the drawing. It is especially important to learn how PI values work.

Moving on to the torso and the tank top, I used a little trick to visually separate the head and make it look like the neck (thanks to the arc() function that I had just learned).  I used rect() and ellipse() to create the torso and then used triangle() to visually separate the body from the arms.  Inspired by one of the works from previous years I also decided to add sunglasses and create a shape similar to the sunglasses that I usually wear using arc(), and use Alpha value  fill() to make my eyes still visible through the lenses.

Background and animations.

To add more entertainment to my self-portrait, I first decided to add some interactivity. As I had just learned about random() and mouseClicked(), I decided to combine them to make the top tank color change with every click. Next, I created the background using rectangular shapes – the beach, the sea, and the sky. I searched for the most realistic RGB color codes, and I think colors look pretty good.

Lastly, I decided to challenge myself a little bit by trying to implement techniques I used in Python here in p5.js. To catch up with the syntax differences, I watched a couple of YouTube videos and searched the Reference on the p5.js website. The thing I am most proud of is the sun movements that I implemented using a Bezier curve. First, I drew the sun’s movement trajectory using bezier(), and then I followed the instructions written in the Reference to use bezierPoint() and make the sun move back and forth. This is a part of the code I am the most proud of.

//Curve for Sun Movement
x1 = 0
x2 = 100
x3 = 300
x4 = 400
y1 = 150
y2 = 0
y3 = 0
y4 = 150
noFill()
 

let x = bezierPoint(x1, x2, x3, x4, t)
let y = bezierPoint(y1, y2, y3, y4, t)

t += 0.001 * move_sun_dir //regulating the speed of the sun
if (t > 1 || t < 0) {
  move_sun_dir *= -1
} //not letting the sun to go away from the screen
  


//Sun
fill(255,255,112)
noStroke()
circle(x, y, 50)



//Beach
fill(255, 234, 200)
noStroke()
rect(200, 400, 400, 200)

//Sea
fill(0, 105, 148)
noStroke()
rectMode(CORNER)
rect(0, 280, 400, sea_level)

sea_level += 0.05 * move_sea_dir //regulating the speed of the sea level

if (sea_level > 40) {
  move_sea_dir = -1;
} 

else if (sea_level < 30) {
  move_sea_dir = 1;
} // keeping the sea level between the rectangle size values

As you might notice, just for the fun of it, I decided to use a similar coding technique to make the sea level rise and fall (in fact it is just the size of the rectangle that changes :)).

Conclusion.

I enjoyed working on my self-portrait, and I am satisfied with the result. I created a nice-looking sketch and already started to integrate some animations and interactivity into my work. Of course, there is tons to learn, and my self-portrait could be even more advanced. I was thinking of adding moving clouds to the sky, drawing palm trees on the beach, or adding ships going back and forth in the sea. I could add many more details, and I am looking forward to learning new tools and features to implement it. The coolest thing that I wanted to add but couldn’t is the change between day and night. As I made the sun move, I realized that it would look awesome if the brightness dimmed every time the sun went down, and vice-versa. I could also add the moon and the stars at night, and make them disappear in the morning.

Overall, this assignment was a great start to my journey in Interactive Media, and I can’t wait to see where this journey will lead me.

 The Whole Code:

let r, g, b;
let t = 0;
let move_sun_dir = 1;
let move_sea_dir = 1;
let sea_level = 30;

function setup() {
  createCanvas(400, 400);
  r = random(255)
  g = random(255)
  b = random(255);
}

function draw() {
  background(135, 206, 235);
  
  
  //Curve for Sun Movement
  x1 = 0
  x2 = 100
  x3 = 300
  x4 = 400
  y1 = 150
  y2 = 0
  y3 = 0
  y4 = 150
  noFill()
 
  
  let x = bezierPoint(x1, x2, x3, x4, t)
  let y = bezierPoint(y1, y2, y3, y4, t)
  
  t += 0.001 * move_sun_dir //regulating the speed of the sun
  if (t > 1 || t < 0) {
    move_sun_dir *= -1
  } //not letting the sun to go away from the screen
    
  
  
  //Sun
  fill(255,255,112)
  noStroke()
  circle(x, y, 50)

  
  
  //Beach
  fill(255, 234, 200)
  noStroke()
  rect(200, 400, 400, 200)
  
  //Sea
  fill(0, 105, 148)
  noStroke()
  rectMode(CORNER)
  rect(0, 280, 400, sea_level)
  
  sea_level += 0.05 * move_sea_dir //regulating the speed of the sea level
  
  if (sea_level > 40) {
    move_sea_dir = -1;
  } 
  
  else if (sea_level < 30) {
    move_sea_dir = 1;
  } // keeping the sea level between the rectangle size values
  
  
  // Head
  fill(255,205,148)
  noStroke()
  ellipse(200, 200, 120, 150);
  
  // Eyes
  fill('white')
  circle(175, 185, 15);
  circle(225, 185, 15);
  
  //Eyeballs
  fill('black')
  circle(175, 185, 5);
  circle(225, 185, 5);
  
  //Mouth
  fill('white')
  stroke('rgb(255,189,201)')
  strokeWeight(4)
  arc(200, 235, 35, 25, 0, PI, CHORD);
  
  //Nose
  fill(224,172,105)
  noStroke()
  ellipse(200, 210, 10, 20);
  
  //Ears
  fill(255,205,148)
  ellipse(140, 190, 20, 30);
  ellipse(260, 190, 20, 30);
  
  //Side Hair
  fill('black')
  quad(145, 145, 165, 150, 160, 185, 145, 180);
  quad(248, 140, 235, 145, 240, 185, 257, 180);
  
  //Top Hair
  fill('black')
  ellipse(width / 2 - 5, 135, 110, 50);
  
  //Eyebrows
  noFill()
  stroke('black')
  arc(175, 180, 16, 16, PI + 0.6, TWO_PI - 0.5)
  arc(225, 180, 16, 16, PI + 0.6, TWO_PI - 0.5)
  
  //Tank top and Torso
  noStroke()
  fill(255,205,148)
  ellipse(150, 370, 100, 200)
  ellipse(250, 370, 100, 200);
  
  rectMode(CENTER)
  fill(r, g, b)
  rect(200, 370, 115, 200);
  
  stroke(255, 234, 200)
  strokeWeight(5)
  triangle(137, 400, 140, 325, 140, 400)
  triangle(260, 400, 260, 325, 263, 400)
  
  //Neck
  noStroke()
  fill(255,205,148)
  arc(200, 270, 50, 50, 0, PI, CHORD);
  
  //SunGlasses
  fill(0, 0, 0, 100)
  stroke('black')
  strokeWeight(0.2)
  arc(175, 178, 22, 37, 0, PI, CHORD)
  arc(225, 178, 22, 37, 0, PI, CHORD)
  strokeWeight(2)
  line(143, 175, 164, 185)
  line(236, 185, 257, 175)
  line(186, 185, 214, 185)
  
}

// Changing color of the tank top
function mouseClicked() { 
  r = random(255)
  g = random(255)
  b = random(255)

}


Assignment 1: Self Portrait

Concept

My p5.js self-portrait is more than simply a picture of my face; it’s a story that illuminates my path to enroll in the “Introduction to Interactive Media” course. The artistic representation of that voyage is this portrait. My conversation with my friends regarding me not being able to enroll in this course until senior spring revolved around how I might be in the hall of fame for not being able to complete my minor because of an introductory course.

The goal of my portrait is to elevate the accomplishment by placing my face on a pedestal and using a lighted stage as the background. It acts as a metaphor for the significant problems I faced since freshmen fall to enroll in this course to complete my minor. Pedestals are typically used to display objects of significant worth or significance. I also thought of adding an interactive element (by clicking the mouse button) that allows me to change the emotions on my face. The face changes from a smile to a laughing face which serves as a cathartic release for the difficulties during the journey.

Sketch

Code 

The code that I am proud of is how I was able to illustrate two different expressions with an easy mouse-click interactive technique. Initially, the value of isLaughing is set to false and when the mouse clicks the value changes to true.

function mouseClicked() {
  // Toggle the laughing state
  isLaughing = !isLaughing; 
}

The drawFace function is the core code for making this sketch possible. This code uses the mouse-toggled laughing boolean variable to show different expressions. The portrait has a lot of facial details that resemble me in real life. The addition of stud-adorned ears, a neck, and a cap enhances the portrait’s authenticity and individuality.

function drawFace(laughing) {
  
  
  // Ears
  fill(skinColor);
  // Left ear   
  ellipse(135, 156, 30, 40);
  // Right ear   
  ellipse(265, 156, 30, 40); 
  
  // Making studs on both ears   
  fill(255,255,255); 
  // stud on left ear   
  ellipse(131, 167, 8, 8);
  fill(255,255,255); 
  // stud on right ear 
  ellipse(269, 167, 8, 8);
  
  // Drawing the neck
  fill(skinColor); 
  rect(175, 206, 50, 60); 
  
  // Drawing the head
  fill(skinColor);
  ellipse(200, 156, 125, 170);
  
  
  // Cap
  fill(0);
  arc(200, 120, 115, 125, PI, TWO_PI, OPEN);
  strokeWeight(10);
  line(150,115,110,115)
  strokeWeight(1);

  if (laughing) {
    // Laughing face
    // Eyes closed
    fill(0);
    // left eye closed    
    ellipse(170, 136, 30, 10); 
    // right eye closed    
    ellipse(230, 136, 30, 10); 

    // Tears
    fill(0, 191, 255);
    // tears from left eye    
    ellipse(165, 151, 10, 25); 
    // tears from right eye
    ellipse(235, 151, 10, 25); 

    // Open mouth - laughing state
    fill(255);
    arc(200, 206, 60, 40, 0, PI, CHORD);

  } else {
    // Smiling Face
    // Eyes
    fill(255);
    // left eye
    ellipse(170, 140, 35, 25); 
    // left eye
    ellipse(230, 140, 35, 25); 
    
    // Pupil     
    fill(0);
    // left eye - pupil  
    ellipse(170, 145, 15, 15); 
    // right eye - pupil 
    ellipse(230, 145, 15, 15); 

    // Mouth
    noFill();
    arc(200, 206, 60, 15, 0, PI); 
  }

  // Nose (same for both faces)
  line(200, 165, 200, 190);
}

Lastly, the concept was achieved by using the pedestal in the center of the room with spotlights showing a significant person.

// Background image of pedestal
function preload(){
  bgImage = loadImage("https://st2.depositphotos.com/1051355/6256/i/450/depositphotos_62569733-stock-photo-illuminated-empty-stage-podiums-for.jpg")
}

Challenges

There were a few challenges that I faced while doing this assignment. Initially, I planned on giving hair to my portrait, however, I was not able to achieve that. So I had to improvise and I made a cap instead.

Another challenge was to determine the x and y coordinates. To solve this issue I printed the cursor’s x and y values in the console using the draw function.

function draw() {
  // finding the value of x and y
  print(mouseX, mouseY)
}

Reflection and Improvements

All the IM courses that I have taken have encouraged me to find meaning behind what I am doing or to show a story. I am happy with the portrait that I have made, it is close to what I look like in real life and also can show the story behind making it.

There is always room for improvement. For example, the portrait may show various emotions depending on which keyboard keys are pressed. Also, the portrait does not have eyebrows, so the eyebrows can follow the mouse when hovering over the portrait.

References

  1. I took a reference from schemecolor.com to use the exact skin color for my portrait.
  2. Another reference was the background image of the pedestal.

Assignment 1: Self Portrait

I learned the basic concepts of p5.js, such as circles, ellipses, and colors, through online tutorials, practice coding, and experimentation. I started out by learning how to create basic shapes using the ellipse and circle functions and then moved on to manipulating more complex shapes such as hair and eyes. I then experimented with different colors to create a more lifelike image. After mastering the basics, I began to understand how to use conditionals to create an animation. I then began to experiment with different speeds and directions to create a more dynamic animation. With each new concept I learned, I was able to create a more realistic selfportrait that accurately captures my personality.

This p5.js code is a moving selfportrait of me. It is a creative piece of code that uses mathematical concepts such as conditionals, variables, and geometry to create an animation. The code is comprised of a setup and draw function and uses variables for the coordinates, directions, and speed of the animation. The setup function creates a canvas of 400x400 pixels and sets the starting positions and speeds of the animation. The draw function uses the variables to draw the self-portrait, which consists of a head with eyes, hair, a nose, and a tongue. The head will move from side to side and bounce up and down when it hits the boundaries. This code captures my playful and creative spirit, as it animates me in a unique and amusing way.

The part of the code that I am most proud of is the part of moving and boundary detection. I was able to connect all pieces of the face into one variable so that all of them move simultaneously. Also, the ternary operator is my way of showing my CS skills(jk).

Reflecting on this project, I am proud of my progress and the creative outcome of the code. I am now confident in my ability to use the fundamental concepts of p5.js to create engaging visuals. However, I am also aware that there is still room for improvement and further exploration. I plan to add user interaction to the animation, for example, allowing users to move the portrait with their mouse. Additionally, I would like to incorporate video sensors to create a more lifelike animation. This could be achieved by tracking a users facial movements and incorporating them into the animation. As I continue to explore the limitless possibilities of p5.js, I look forward to creating increasingly complex animations and engaging interactive experiences.