My Sketch
My concept
For this project, I wanted to depict a regular “headshot” of myself using different p5.js functions. My preference for aesthetic leans toward minimalism and simplicity, so I tried to make the portrait look “clean” and “slick” instead of super realistic. I chose a pink-green color scheme since one of my favorite drinks is strawberry matcha, and I want to incorporate parts of my personality into the portrait.
Ultimately, my goal for this project was to explore a variety of features on p5.js, so I practiced with the different primitive shapes we learned in class, as well as researched some other functions on my own.
My highlight code
As ironic as it may sound…my favorite part about my portrait is my background! Initially, I had a 1-color pink background, but it seemed too boring and I wanted some personality! I decided to create a checkered background with 2 different shades of pink. In order to create this, I worked with nested for loops, running variables i and j until the canvas width/height and having them as the (x,y) coordinates for the colored squares. I had previous coding experience with python and java, so I only really had to refer to p5 reference for the correct syntax.
//print checkered background
//loop 1 -- prints odd numbered rows
for (let i =0; i<width; i += 100 ) {
//ROWS--loop until width of canvas, increment by 100 each time to "skip" a block as it goes from left to right
for (let j =0; j<height; j += 100 ) {
//COLUMNS--loop until height of canvas, increment by 100 each time to "skip" a block as it goes from top to bottom
fill("#ffb8bb")
noStroke()
//the top x,y coordinate is the i & j that increments
square(i,j,50);
}
}
//second loop-print even numbered rows
/* similar logic to previous loop except this time i start i from 50 to create the "checkered" effect*/
for (let i =50; i<width; i += 100 ) {
for (let j =50; j<height; j += 100 ) {
fill("#ffb8bb")
noStroke()
square(i,j,50);
}
}

I’m also really proud of how I made the mouth. I knew I wanted a blob for an open-mouth instead of a smiley line because it looks cuter (and also less creepy). However, a blob isn’t a primitive shape and therefore I couldn’t figure out how to create the mouth the way I had envisioned. Then, it suddenly clicked that I can totally make it a super small arc with a huge stroke (I felt like a genius), which is exactly what I did to achieve the darker red mouth.
//mouth -- blob is created using an small arc with huge stroke
stroke("#a20b0b")
strokeWeight(25)
noFill()
arc(200,240,50,50,(PI/3),(2*PI/3));
How this sketch was made

I started by planning out what would be the bottom-most layer (excluding the background), which would be the hair. The hair is simply 2 overlapping ellipses, which creates the middle hair part. Then, my head looked like an egg so I had to put some bangs. I did this by having 2 lines with a huge stroke, covering the top diagonally. The photo aside illustrates this, with the bangs being a transparent green for demonstration.
The eyes are just many circles placed on top of one another, while the eyelid is a half-circle arc (no fill) that sits behind the white of the eye. Because most of the features on this portrait (not my face :)) are symmetrical, it was quite easy to duplicate something twice. The nose is, also, just a small arc positioned in the center of the face.

The neck has two parts to it: a rectangle and the collar part, which is the bottom half of a circle. In between the neck and the collar is a green shirt, which I created by using a rectangle. I was really contemplating on whether to use a rectangle or a quadrilateral, since with a quadrilateral, I can make the slant of the arms, which I prefer a lot more. However, I then realized that the corners of these shapes are too sharp, which makes the body boxy and therefore less coherent. This could be fixed with border-radius, which allows for rounded corners, but there were only available as a parameter for rectangles, which I decided to stick with at the end.
function wink() {
//first I cover the original eye using an ellipse the blends with the face
fill("#d9a582");
noStroke();
ellipse(230,195,60,60);
stroke("#341504")
strokeWeight(3)
noFill();
//then the 2 lines
line(245,175,212,191);
line(245,210,212,191);
//after wink() runs for 500 milliseconds, openEye() runs for the rest of the setInterval which would be 2.5 secs in this case
setTimeout(openEye, 500);
}
I created a function wink() to also play around with animation. This function draws a large ellipse on top of my right eye in the same color as my face, which covers it. Then, 2 lines created the “<” which indicates a wink. Then, I put setInterval(wink, 3000) in my setup function so that it winks after 3 seconds. But then, I stumbled upon a bug as the person wasn’t winking when I ran the code at all! I then realized that the draw function, which currently contains all of my code, immediately redraws the face on top of my winked eye. Since the portrait was completely static at this point, I moved all of my drawing to setup(). This solves the issue, but then my person stays winked. I tried solving this issue by having another function that draws the original eye, called openEye() and add setTimeout(openEye, 500) to my wink(). What this does, essentially, is have the person wink for 500 milliseconds and then the normal eye appears for 2.5 seconds, and then another interval happens where it winks again. I’m not sure if this is the most optimized way to create this animation, but I had fun playing around with the facial expressions for sure!
Reflection
Overall, I’m really happy with how my portrait turned out! I think I have, in general, achieved the “clean” look I was aiming for. I also love how colorful and vibrant the sketch is, I feel like it captures my energy really well. One thing I feel like I could improve if I had more time is to make it more like me! This would be a bit of a challenge since I don’t like anything that is too detailed, but I’d like to put myself through those challenges some time! I could try having little blushes/freckles, or a different accessory (since I never wear bows).
Also, a mistake I made in the beginning was not determining the appropriate canvas size. I kept it at the default size, 400×400. I only realized after sketching the head and the hair that this wouldn’t leave me enough space for the body, so I had to change the height to 500 pixels. In future projects, I would like to avoid this mistake as I could have to manually shift everything up/down/left/right by a certain value (which is kind of a hideous thing to do :)).
Resources I Used
https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
https://www.w3schools.com/jsref/met_win_setinterval.asp
https://p5js.org/reference/p5/for
https://p5js.org/reference/p5/arc/
https://coolors.co/f58484-ffb8bb-d9a582-12631c-68d34a
No Artificial Intelligence was used in the making of this sketch or its documentation.