Overview
Following the sessions on Week 1, our first assignment was to create a self-portrait using p5.js. Last semester I took Communications Lab, so I was familiar with the website, but I haven’t gone into such depts before, and for this assignment I decided to create my self-portrait with a little additional information about me, which is that I don’t like the rain.
I really wanted to use as many of the available 2D shapes as possible, such as the arc, the ellipse, the circle, the line, and the rectangle, along with some of the other resources like mouseX, mouseY, the mouseIsPressed, or constrain. I have tried to create myself a little challenge but also not put too much pressure on myself to put absolutely everything into this first assignment.
Process
For this assignment I decided to create an entirely new project and make my portrait out of scratch. I was sure that I wanted to add some basic interaction, just for a little practice and to make it more fun. I made the biggest components first, my head, my body, and my hair, and then moved on to the smaller details like my bangs, my eyes, nose, mouth, and my glasses. For all of these elements, I relied heavily on the p5.js references, but didn’t use any other external sources. I also decided after my body was fully made to put something in the background as well, just to make it a little less plain, and then came the idea that I will use my interaction here and show how much I don’t like standing in the rain. As a last touch, I also added some shading, just to play a little with the layers as well, and to add a little depth to it.
The Code
function setup() {
createCanvas(400, 600);
}
function draw() {
background("lightblue");
//Sun
fill("yellow");
circle(50, 50, 60);
fill("black");
textFont('Courier New');
text('click and see what happens', 110, 60);
noStroke();
//Hair Shadow
fill(127, 80);
rect(104, 203, 200, 210,);
//Hair
fill("yellow");
rect(100, 200, 200, 210,);
//Body Shadow on BG
fill(120, 120);
triangle(209, 300, 110, 600, 300, 600);
//Body
fill("brown");
triangle(200, 300, 110, 600, 300, 600);
//Shadow on Body
fill(127, 70);
noStroke();
ellipse(200, 400, 60, 30);
//Head
fill("#F7D4C4");
circle(200, 300, 200);
//Glasses
noFill();
stroke(0);
strokeWeight(2);
rect(145, 283, 45, 35, 5);
rect(205, 283, 45, 35, 5);
line(190, 300, 205, 300);
//Eyes
fill(255);
stroke(-2);
circle(170, 300, 30);
let px = constrain(mouseX, 165, 175);
let py = constrain(mouseY, 295, 308);
fill (0);
circle(px, py, 10);
fill(255);
stroke(0);
circle(225, 300, 30);
let px2 = constrain(mouseX, 222, 230);
let py2 = constrain(mouseY, 295, 310);
fill (0);
circle(px2, py2, 10);
//Nose
stroke(1);
strokeWeight(2);
line(197, 315, 197, 330);
//Bangs shadow
noStroke();
fill(127,30);
arc(100, 205, 200, 200, 0, HALF_PI);
arc(300, 205, 200, 200, HALF_PI, PI);
//Bangs
noStroke();
fill("yellow");
arc(100, 200, 200, 200, 0, HALF_PI);
arc(300, 200, 200, 200, HALF_PI, PI);
//Mouth
noFill();
stroke(255, 0, 0);
strokeWeight(4);
arc(200, 340, 60, 40, 0, PI);
//Hand shadow
noStroke();
fill(127, 127);
rect(164, 473, 20, 50);
rect(229, 473, 20, 50);
//Hands
fill("#F7D4C4");
rect(160, 470, 20, 50);
rect(225, 470, 20, 50);
if(mouseIsPressed){
background(220);
noStroke();
//Clouds
fill(255);
circle(60,50,40);
circle(85,50,50);
circle(108,50,40);
circle(210,120,60);
circle(245,120,70);
circle(280,120,60);
//Rain
stroke("blue");
strokeWeight(3);
line(70, 90, 80, 120);
line(90, 110, 100, 140);
line(100, 90, 120, 150);
noStroke();
//Hair Shadow
fill(127, 80);
rect(104, 203, 200, 210,);
//Hair
fill("yellow");
rect(100, 200, 200, 210,);
//Body Shadow on BG
fill(120, 120);
triangle(209, 300, 110, 600, 300, 600);
//Body
fill("brown");
triangle(200, 300, 110, 600, 300, 600);
//Shadow on Body
fill(127, 70);
noStroke();
ellipse(200, 400, 60, 30);
//Head
fill("#F7D4C4");
circle(200, 300, 200);
//Glasses
noFill();
stroke(0);
strokeWeight(2);
rect(145, 283, 45, 35, 5);
rect(205, 283, 45, 35, 5);
line(190, 300, 205, 300);
//Nose
stroke(1);
strokeWeight(2);
line(197, 315, 197, 330);
//Bangs shadow
noStroke();
fill(127,30);
arc(100, 205, 200, 200, 0, HALF_PI);
arc(300, 205, 200, 200, HALF_PI, PI);
//Bangs
noStroke();
fill("yellow")
arc(100, 200, 200, 200, 0, HALF_PI);
arc(300, 200, 200, 200, HALF_PI, PI);
//Eyes
fill(255);
stroke(0);
circle(170, 300, 30);
fill (0);
circle(170, 300, 10);
fill(255);
stroke(0);
circle(225, 300, 30);
fill (0);
circle(225, 300, 10);
//Mouth
noFill();
stroke(255, 0, 0);
strokeWeight(4);
arc(200, 365, 60, 40, PI, TWO_PI);
//Hand shadow
noStroke();
fill(127, 127);
rect(164, 473, 20, 50);
rect(229, 473, 20, 50);
//Hands
noStroke();
fill("#F7D4C4");
rect(160, 470, 20, 50);
rect(225, 470, 20, 50);
}
}
I can be a rather messy person in real life, and to compensate that I try to keep my online life a little more organised. I tried my best to divide all parts of the code, make it clear what piece of code is which part of the portrait and that made it a lot easier to later go back to it and adjust or correct certain things. It came in very handy for example when I was adding the shadows, especially the bangs, because it was a lot easier to find the “Glasses” and the “Bangs” chunks, between which I wanted to place my shadow.
Something that took a little more time but made me very happy to see it work were the moving eyes. I used the constrain calculation, which I had to try multiple times to work. I had to understand which parameter constrains which side, but after I figured that out, I was able to constrain my “pupil” to stay in the “eye” but still move.
//Eyes fill(255); stroke(-2); circle(170, 300, 30); let px = constrain(mouseX, 165, 175); let py = constrain(mouseY, 295, 308); fill (0); circle(px, py, 10); fill(255); stroke(0); circle(225, 300, 30); let px2 = constrain(mouseX, 222, 230); let py2 = constrain(mouseY, 295, 310); fill (0); circle(px2, py2, 10);
Reflection and Ideas
As a reflection, I had a lot of ideas for this project that I couldn’t do in the end. For example, I originally wanted my bangs to move as if it were the wind messing them up (which is another very important part of my everyday life), but I found it a little too difficult. I would love to explore more libraries in the future to find out about new techniques that could have also made the process of making this portrait easier or just different. Another thing I would also love to learn is how to make the movements smoother. I really love the eyes, however I would prefer them to move smoother than they do right now. But despite knowing that there is a lot of room for improvement, for this first project, my goal was not to go overboard but rather to explore the basics of p5.js, so overall I am happy with the results.