xxxxxxxxxx
let mpss;
let faces = [];
let offset;
let square_type;
function setup() {
createCanvas(800, 800);
colorMode(HSB, 360, 100, 100, 100);
angleMode(DEGREES);
offset = width / 15;
mpss = new mPSS(width - offset * 2);
square_type = [
mPSS.tfTypeIdOriginal,
mPSS.tfTypeIdRotate90,
mPSS.tfTypeIdRotate180,
mPSS.tfTypeIdRotate270,
mPSS.tfTypeIdMirror,
mPSS.tfTypeIdMirrorRotate90,
mPSS.tfTypeIdMirrorRotate180,
mPSS.tfTypeIdMirrorRotate270,
];
const squares = mpss.getSquares(random(square_type));
squares.forEach((sq) => {
// square(sq.x, sq.y, sq.size);
let face = new Face(sq.centerX, sq.centerY, sq.size);
faces.push(face);
});
}
function draw() {
background(0, 0, 20);
push();
translate(offset, offset);
for (let face of faces) {
face.display();
}
pop();
}
class Face {
constructor(center_x, center_y, face_w) {
let skin_tones = ["#ffe2c6", "#ffd7ae", "#dfc4a8", "#fde7d6", "#e7c6a4"];
this.center_x = center_x;
this.center_y = center_y;
this.face_w = face_w;
this.mouth_w = face_w / random(2, 5);
this.mouth_h = face_w / random(2, 4);
this.mouth_x = 0;
this.mouth_y = this.mouth_h / 1.5 - this.mouth_h / 5;
this.tooth_h = face_w / 10;
this.tooth_num = int(random(2, 8));
this.angle = random(360);
let c1 = random(skin_tones);
let c2 = random(skin_tones);
while (c1 == c2) {
c2 = random(skin_tones);
}
this.skin = lerpColor(color(c1), color(c2), random());
this.w = face_w;
this.freq = random(1, 10);
this.ew = (this.face_w / 2 - this.mouth_w / 2) * random(0.5, 1);
this.eh = this.ew / random(1, 2.5);
this.en = random(1.5, 4);
this.eangle = random(360);
this.eb_h = random(this.eh * 0.5, this.eh * 1.5);
this.hair_color = color(random(360), 100, 10);
this.tooth_arr = [];
for (let i = 0; i < (this.tooth_num + 1) * 2; i++) {
this.tooth_arr.push(random() < 0.9);
}
}
display(angle = 0) {
rectMode(CENTER);
push();
translate(this.center_x, this.center_y);
scale((this.w - 10) / this.w);
fill(this.skin);
noStroke();
rect(0, 0, round(this.w), round(this.w), this.w / 10);
drawingContext.clip();
rotate(angle);
this.drawMouth();
this.drawEye(
this.face_w / 2 - (this.ew * 2) / 3,
-this.face_w / 10,
this.ew,
this.eh,
this.en,
this.angle,
this.hair_color,
this.eb_h
);
this.drawEye(
-this.face_w / 2 + (this.ew * 2) / 3,
-this.face_w / 10,
this.ew,
this.eh,
this.en,
this.angle,
this.hair_color,
this.eb_h
);
pop();
}
drawMouth() {
push();
translate(0, this.mouth_y);
let mouth_h = constrain(
(this.mouth_h / 2) * sin(this.angle + frameCount * this.freq) +
this.mouth_h / 4,
this.tooth_h,
this.mouth_h
);
// stroke(0, 0, 20);
fill(0, 0, 20);
rect(0, 0, this.mouth_w, mouth_h, this.mouth_w);
drawingContext.clip();
fill(0, 50, 80);
arc(
0,
this.mouth_h / 2,
this.mouth_w,
this.mouth_h * sin(frameCount * this.freq),
0,
360
);
translate(-this.mouth_w / 2, -mouth_h / 2);
let n = 0;
for (let i = 0; i <= this.tooth_num; i++) {
let tx = map(i, 0, this.tooth_num, 0, this.mouth_w);
let ty = 0;
let tw = this.mouth_w / this.tooth_num;
let th = this.tooth_h;
let tr = tw / 3;
fill(0, 0, 100);
if (this.tooth_arr[n++ % this.tooth_arr.length]) {
rect(tx, ty, tw, th, 0, 0, tr, tr);
}
if (this.tooth_arr[n++ % this.tooth_arr.length]) {
rect(tx, ty + mouth_h, tw, th, tr, tr, 0, 0);
}
}
pop();
}
drawEye(x, y, w, h, d, angle, eye_color, eb_h) {
let c1 = color(hue(eye_color), saturation(eye_color) / 2, 40);
let c2 = color(hue(eye_color), saturation(eye_color) / 2, 25);
push();
// stroke(0, 0, 20);
fill(0, 0, 95, 80);
// noStroke();
this.drawSuperEllipse(x, y, w, h, d);
let ew = w;
drawingContext.clip();
let x2 = (cos(angle) * ew) / 8;
let y2 = (cos(angle) * ew) / 8;
let x3 = (cos(-45) * ew) / 5;
let y3 = (sin(-45) * ew) / 5;
push();
translate(x, y);
translate(x2, y2);
fill(c2);
// noStroke();
circle(0, 0, ew / 1.5);
fill(c1);
circle(0, 0, ew / 2.24);
fill(0, 0, 95, 50);
// noStroke();
circle(x3, y3, ew / 6);
pop();
pop();
push();
translate(x, y - eb_h);
noFill();
stroke(c2);
strokeWeight(ew / 7);
arc(0, 0, ew, ew / 2, 180 + 45, 360 - 45);
pop();
}
drawSuperEllipse(x, y, w, h, n) {
push();
translate(x, y);
scale((w - 5) / w);
let na = 2 / n;
beginShape();
for (let angle = 0; angle < 360; angle += 2) {
let x = ((pow(abs(cos(angle)), na) * w) / 2) * this.sgn(cos(angle));
let y = ((pow(abs(sin(angle)), na) * h) / 2) * this.sgn(sin(angle));
vertex(x, y);
}
endShape(CLOSE);
pop();
}
sgn(val) {
if (val == 0) {
return 0;
}
return val / abs(val);
}
}