<iframe src="https://editor.p5js.org/cc8800/full/nqMMvR6BL"></iframe> width=404 height=404
<iframe src="https://editor.p5js.org/cc8800/full/nqMMvR6BL"></iframe> width=404 height=404
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.
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.
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 :)).
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) }
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
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 life–like 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 self–portrait that accurately captures my personality.
This p5.js code is a moving self–portrait 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 life–like animation. This could be achieved by tracking a user’s 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.