I want to create a simple cartoon face that has many expressions. Therefore, I add many variables including the mouth, hair, eyebrow, and so on. The outcome looks good.
// Setting variables for coding facial actions
var eyeSizeX = 20;
var eyeSizeY = 20;
var faceWidth = 100;
var faceHeight = 150;
var mouthExpression = 1;
var noseExpression = 1;
var hairExpression = 1;
var hairSize = 0.4;
var mouthSize = 0.1;
var r = 225
var g = 175
var b = 125
var rot = 0;
var eyeOffAry = [-1, -0.5, 0, 0.5, 1];
var eyeOffs = 0;
function setup() {
createCanvas(480, 640);
angleMode(DEGREES);
}
function draw() {
background(180);
//draw face
fill(r, g, b);
strokeWeight(0);
ellipse(width / 2, height / 2, faceWidth, faceHeight);
//draw hair
//hair
if (hairExpression <= 1) {
fill(r-100, g-100, b-100);
arc(width / 2, height / 2, faceWidth, faceHeight, faceWidth*hairSize-160, -faceWidth*hairSize-20, CHORD);
}
//beard
else if (hairExpression >= 1 & hairExpression <= 2) {
stroke(r-100, g-100, b-100);
strokeWeight(faceWidth/5);
arc(width / 2, height / 2, faceWidth, faceHeight, faceWidth*hairSize+40, 140-faceWidth*hairSize);
}
//hair line
else if (hairExpression >= 2 & hairExpression <= 3) {
stroke(r-100, g-100, b-100);
strokeWeight(faceWidth/5);
arc(width / 2, height / 2, faceWidth, faceHeight, -180+faceWidth*hairSize, -faceWidth*hairSize);
}
//long hair
else if (hairExpression >= 3 & hairExpression <= 4) {
//draw long hair behind face
rectMode(CORNER);
fill(r-100, g-100, b-100);
stroke(r-100, g-100, b-100);
strokeWeight(faceWidth/6);
rect(width/2-faceWidth/2, height/2, faceWidth, faceHeight);
//draw face forward
fill(r, g, b);
strokeWeight(0);
ellipse(width / 2, height / 2, faceWidth, faceHeight);
//draw hair forward
fill(r-100, g-100, b-100);
arc(width / 2, height / 2, faceWidth, faceHeight, faceWidth*hairSize-160, -faceWidth*hairSize-20, CHORD);
noFill();
stroke(r-100, g-100, b-100);
strokeWeight(faceWidth/5);
arc(width / 2, height / 2, faceWidth, faceHeight, -180, 0);
}
//draw eyes
stroke(0);
strokeWeight(0);
var eyeLX = width / 2 - faceWidth * 0.15;
var eyeRX = width / 2 + faceWidth * 0.15;
fill(255);
ellipse(eyeLX, height / 2, eyeSizeX, eyeSizeY);
ellipse(eyeRX, height / 2, eyeSizeX, eyeSizeY);
fill(0);
ellipse(eyeLX + eyeOffs*(eyeSizeX / 4), height / 2, eyeSizeX / 2, eyeSizeY / 2);
ellipse(eyeRX + eyeOffs*(eyeSizeX / 4), height / 2, eyeSizeX / 2, eyeSizeY / 2);
//draw noses
fill(r-100,g-100,b-100);
if (noseExpression <= 1) {
ellipse(width/2, height/2 + faceHeight*0.05, faceWidth/20, faceHeight/20);
} else if(noseExpression >= 1 & noseExpression <=2) {
rectMode(CENTER);
rect (width/2, height/2 + faceHeight*0.08, faceWidth/20, 1.3*faceHeight/20);
} else {
triangle(width/2, height/2 + faceHeight*0.05, width/2-faceWidth/20, height/2 + faceHeight*0.1, width/2+faceWidth/20, height/2 + faceHeight*0.1)
}
//draw eyebrows
var ebrowLX1 = width / 2 - faceWidth * 0.2;
var ebrowLY1 = height / 2 - faceHeight * 0.15;
var ebrowLX2 = width / 2 - faceWidth * 0.35;
var ebrowLY2 = height / 2 - faceHeight * 0.15;
var ebrowRX1 = width / 2 + faceWidth * 0.2;
var ebrowRY1 = height / 2 - faceHeight * 0.15;
var ebrowRX2 = width / 2 + faceWidth * 0.35;
var ebrowRY2 = height / 2 - faceHeight * 0.15;
noFill();
stroke(0);
strokeWeight(5);
translate((ebrowLX1+ebrowLX1)/2, (ebrowLY1+ebrowLY2)/2);
rotate(rot);
line(10, 0, -10, 0);
rotate(-rot);
translate(-(ebrowLX1+ebrowLX1)/2, -(ebrowLY1+ebrowLY2)/2);
translate((ebrowRX1+ebrowRX1)/2, (ebrowRY1+ebrowRY2)/2);
rotate(-rot);
line(10, 0, -10, 0);
rotate(rot);
translate(-(ebrowRX1+ebrowRX1)/2, -(ebrowRY1+ebrowRY2)/2);
//draw mouth
var mouthLX = width / 2 - faceWidth * 0.25;
var mouthLY = height / 2 + faceHeight * 0.25;
var mouthRX = width / 2 + faceWidth * 0.25;
var mouthRY = height / 2 + faceHeight * 0.25;
noFill();
strokeWeight(0);
if (mouthExpression <= 1) {
//open happy mouth
fill(255);
beginShape();
curveVertex(mouthLX, mouthLY);
curveVertex(mouthLX, mouthLY);
curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY+faceHeight*0.1);
curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY+faceHeight*0.1);
curveVertex(mouthRX, mouthRY);
curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY+faceHeight*mouthSize/2);
curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY+faceHeight*mouthSize/2);
curveVertex(mouthLX, mouthLY);
curveVertex(mouthLX, mouthLY);
endShape();
} else if (mouthExpression >= 1 & mouthExpression <= 2) {
//open sad mouth
fill(255);
beginShape();
curveVertex(mouthLX, mouthLY);
curveVertex(mouthLX, mouthLY);
curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY-faceHeight*0.1);
curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY-faceHeight*0.1);
curveVertex(mouthRX, mouthRY);
curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY-faceHeight*mouthSize/2);
curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthLY-faceHeight*mouthSize/2);
curveVertex(mouthLX, mouthLY);
curveVertex(mouthLX, mouthLY);
endShape();
} else if (mouthExpression >= 2 & mouthExpression <= 3){
//closed mouth
strokeWeight(5);
beginShape();
curveVertex(mouthLX, mouthLY);
curveVertex(mouthLX, mouthLY);
curveVertex(0.5*(mouthLX+mouthRX)-faceWidth*0.1, mouthRY-faceHeight*mouthSize);
curveVertex(0.5*(mouthLX+mouthRX)+faceWidth*0.1, mouthLY-faceHeight*mouthSize);
curveVertex(mouthRX, mouthRY);
curveVertex(mouthRX, mouthRY);
endShape();
} else if (mouthExpression >= 3 & mouthExpression <= 4){
//no expression
strokeWeight(5);
beginShape();
curveVertex(mouthLX, mouthLY);
curveVertex(mouthLX, mouthLY);
curveVertex(mouthRX, mouthRY);
curveVertex(mouthRX, mouthRY);
endShape();
}
}
//Randomize the value of variables when the user clicks to generate a new random face
function mousePressed() {
faceWidth = random(100, 200);
faceHeight = random(150, 250);
eyeSizeX = random(20, 30);
eyeSizeY = random(10, 30);
mouthExpression = random(0, 4);
noseExpression = random(0, 3);
hairExpression = random(0, 5);//give some chance between 4-5 for no hair
mouthSize = random(-0.1, 0.1);
hairSize = random(0.1, 0.2);
eyeOffs = random(eyeOffAry);
r = random(100, 255);
g = random(100, 255);
b = random(100, 255);
rot = random(-45, 45);
}