Timothy Liu — Project 02 — Variable Face

tcliu-OpenEnded-02

// Timothy Liu
// 15104 Section C
// Open Ended-02

// facial features (variables)
var eyeWidth = 25;
var eyeHeight = 15;
var pupilWidth = eyeWidth / 2;
var pupilHeight = 11 * eyeHeight / 16;
var noseWidth = 15;
var noseHeight = 40;
var earSize = 30;
var headWidth = 125;
var headHeight = 150;
var mouthWidth = 60;
var mouthHeight = 40;
var mouthStart;
var mouthEnd;
var skin1 = "#FFD3A1";
var eyeL;
var eyeR;

// body shape and size (variables)
var bodyWidth = 200;
var bodyHeight = 370;
var colorR = 105;
var colorG = 64;
var colorB = 122;

// hat dimensions and color (variables)
var hatR = 14;
var hatG = 28;
var hatB = 117;
var hatBottom;

// function time!
function setup() {
    
    createCanvas(600, 480);
    mouthStart = TWO_PI;
    mouthEnd = PI;
    eyeL = width / 2 - headWidth / 5;
    eyeR = width / 2 + headWidth / 5;
    hatBottom = height / 4 - headHeight / 6;
    // initializing P5.js functions in setup()

}
 
function draw() {

    // background color
    background(240, 196, 101);
    noStroke();

    // ears
    fill(skin1);
    ellipse(width / 2 - headWidth / 2, height / 4, headWidth / 8, headHeight / 6);
    ellipse(width / 2 + headWidth / 2, height / 4, headWidth / 8, headHeight / 6);

    // neck
    fill(skin1);
    rect(width / 2 - headWidth / 4, height / 4 + headHeight / 4, headWidth / 2, headHeight);

    // head and face
    fill(skin1);
    ellipse(width / 2, height / 4, headWidth, headHeight);

    // bucket hat
    fill(hatR, hatG, hatB);
    quad(width / 2 - headWidth / 2, hatBottom, width / 2 - headWidth / 3, height / 4 - headHeight / 2, 
    	width / 2 + headWidth / 3, height / 4 - headHeight / 2, width / 2 + headWidth / 2, hatBottom);
    rect(width / 2 - 2 * headWidth / 3, hatBottom, headWidth * 1.35, headWidth / 32);

    // eyeballs
    fill("white");
    ellipse(eyeL, height / 4 - height / 48, eyeWidth, eyeHeight);
    fill("white");
    ellipse(eyeR, height / 4 - height / 48, eyeWidth, eyeHeight);

    // pupils
    fill(59, 35, 18);
    ellipse(eyeL, height / 4 - height / 48, pupilWidth, pupilHeight);
    fill(59, 35, 18);
    ellipse(eyeR, height / 4 - height / 48, pupilWidth, pupilHeight);

    // nose
    fill("#D39972");
    arc(width / 2, height / 4 + headHeight / 8, noseWidth, noseHeight, PI, TWO_PI);

    // mouth
    fill(255, 150, 150);
    arc(width / 2, height / 3, mouthWidth, mouthHeight, mouthStart, mouthEnd, CHORD);

    // body and shirt
    fill(colorR, colorG, colorB);
    arc(width / 2, 5 * height / 6, bodyWidth, bodyHeight, PI, TWO_PI);

    // pants
    fill("#003366");
    rect(width / 2 - bodyWidth / 2, 5 * height / 6, bodyWidth, height / 6);

    // thigh gap
    fill(240, 196, 101);
    rect(width / 2 - bodyWidth / 8, 15 * height / 16, bodyWidth / 4, bodyWidth / 4)
}

function mousePressed() {

    // brackets to denote an array. The coinFlip variable helps determine whether it's a smile or frown.
    var coinFlip = random([0, 1]);

    // randomly generating head proportions including eyes, face size, pupil, nose, and mouth.
    headWidth = random(100, 200);
    headHeight = random(121, 180);
    eyeWidth = random(15, 40);
    eyeHeight = random(10, 20);
    eyeL = width / 2 - headWidth / 5;
    eyeR = width / 2 + headWidth / 5;
    pupilSize = 9 * eyeWidth / 16;
    noseWidth = random(10, 30);
    noseHeight = random(20, 50);
    mouthWidth = random(20, 60);
    mouthHeight = random(20, 60);

    // randomly generating body size and color.
    bodyWidth = random(170, 350);
    colorR = random(0, 255);
    colorG = random(0, 255);
    colorB = random(0, 255);

    // randomly generating hat color.
    hatR = random(0, 255);
    hatB = random(0, 255);
    hatG = random(0, 255);

    // this is an array of different hex values for skin tones.
    // the program randomly selects a skin tone every time the mouse is pressed.
    skin1 = random(["#FFD3A1", "#F5CB9A", "#C39582", "#FFCEB4", "#A57E6E", "#EABD9D", "#FFCEB4", "#DEAB7F", "#FFDCB1"]);
    
    // this if statement helps determine whether the character is smiling or frowning using the coinFlip variable defined above. 
    if (coinFlip == 0) {
        mouthStart = 6.28;
        mouthEnd = 3.14;
        // Smiley mouth
    } else {
    	mouthStart = 3.14;
    	mouthEnd = 6.28;
    	// Frowny mouth
    }

    // condition to ensure that the Smiley mouth never sticks out past the chin
    // note: this was originally an if-and statement, but the ampersand was causing issues with WordPress embedding.
    if (mouthStart == 6.28) {
        if ((height / 3 + mouthHeight) > (height / 4 + headHeight / 2)) {
            mouthHeight = mouthHeight / 2;
        }
    }

    // condition to ensure Frowny mouth never touches the nose
    if (mouthStart == 3.14) {
        if ((height / 3 - mouthHeight) < (height / 4 + headHeight / 8 + noseHeight)) {
            mouthHeight = mouthHeight / 2;
        }
    }

}

This project was a fun challenge for me because it required a heavy amount of step-by-step variable referencing, but it also encouraged me to think very logically. Every time I set up coordinates, I actively made sure to question if I could use a variable to simplify my code, and this made it significantly easier to randomize the face (as well as other features) later because all of my variables were already consolidated.

I enjoyed getting to play with an abstract art style, and I made my characters reflect that; they each have simplified features, but my program incorporates a wide array of body types and shapes. I’ve come away from this project with a much stronger understanding of how to utilize local and global variables, as well as how to use if-else statements to set up different conditions to ensure my faces didn’t distort in odd ways.

Leave a Reply