Inspiration
I initially had no idea how I wanted my portrait to look, but I knew I wanted to do something a bit conceptually out there. Probably something within the lines of weird colors and shapes that don’t make sense.
The Process
I decided I wanted a background that cycled through colors and was dynamic. I looked at the color picker on google and moved the color slider bar around and saw that the HSV method of describing color would be easiest to represent as a rainbow-like cycle in HSV was to go from (0°,x%,y%) to (360°,x%,y%) and back down. I found a converter for HSV to RGB and wrote a function that translated HSV to RGB from this page in p5.js and had a variable increase that I used as a parameter.
function hsv_to_rgb(h, s, v) {
h = h % 360;
let c = v * s;
let x = c * (1 - abs(((h / 60) % 2) - 1));
let m = v - c;
let rp, gp, bp;
//r,g,b prime depend on value of h in degrees
if (0 <= h && h < 60) {
[rp, gp, bp] = [c, x, 0];
} else if (60 <= h && h < 120) {
[rp, gp, bp] = [x, c, 0];
} else if (120 <= h && h < 180) {
[rp, gp, bp] = [0, c, x];
} else if (180 <= h && h < 240) {
[rp, gp, bp] = [0, x, c];
} else if (240 <= h && h < 300) {
[rp, gp, bp] = [x, 0, c];
} else{
[rp, gp, bp] = [c, 0, x];
}
//return r g b values
return [(rp + m) * 255, (bp + m) * 255, (gp + m) * 255];
}
I then decided to make a function to draw a shirt, using the cycle but switching the b and g values so that a different cycle is used. Using variables, I centered the shirt and added a small triangle for the neck.
let shirtheight = 180;
let shirtwidth = 250;
let triangleoffset = 20;
let triangleheight = 20;
function drawshirt(r,b,g){
//drawing a shirt with random colors
fill(r,b,g)
stroke(200)
rect((width-shirtwidth)/2, height-shirtheight, shirtwidth, shirtheight, 60, 60, 0, 0);
//draw a triangle over the shirt
fill(255)
triangle(width/2+triangleoffset,height-shirtheight,width/2-triangleoffset,height-shirtheight,width/2,height-shirtheight+triangleheight)
}
Then I looked to add a head with some dynamic parts: a moving head, pupils, mouth, and an offset so I can have multiple heads. All these parts were made with variables for height and width so that all objects function with varying canvas sizes. the use of the min and max functions are for creating bounds for the movement of body parts. I decided to use a sine function with bounds that moved with the shade of the background to have some type of synchronization with the background, but it’s difficult to see it on the canvas. The mouth is bound rectangularly, and the user can move their cursor to change the shape.
function drawface(offsetx, offsety){
fill(255)
//lets draw a head
rect((width-headwidth)/2+offsetx, height-shirtheight-headheight+offsety, headwidth, headheight, 60, 60, 60, 60);
fill(255)
//add some eyes
rect((width-headwidth)/2+eyeoffset+offsetx, height-shirtheight-headheight+eyeheightoffset+offsety, leyewidth, leyeheight, 60, 60, 60, 60);
rect(width-(width-headwidth)/2-eyeoffset-reyewidth+offsetx, height-shirtheight-headheight+eyeheightoffset+offsety, reyewidth, reyeheight, 60, 60, 60, 60);
//add some pupils that move, bounded by the height of the eyes
fill(0)
rect(width-(width-headwidth)/2-eyeoffset-reyewidth+offsetx, min(max(height-shirtheight-headheight+eyeheightoffset,height*sin(currbg/lpupiledelay)),height-shirtheight-headheight+eyeheightoffset+reyeheight-pupilheight)+offsety, reyewidth, pupilheight, 60, 60, 60, 60);
rect((width-headwidth)/2+eyeoffset+offsetx, min(max(height-shirtheight-headheight+eyeheightoffset,height*sin(currbg/rpupiledelay)),height-shirtheight-headheight+eyeheightoffset+leyeheight-pupilheight)+offsety, leyewidth, pupilheight, 60, 60, 60, 60);
//add a triangular mouth in the center of the face
triangle(
min(width/2+mouthoffset+offsetx,max(mouseX,width/2-mouthoffset+offsetx)),
min(max(height-shirtheight-2*mouthoffset+offsety, mouseY),height-shirtheight+offsety),
width/2+mouthoffset+offsetx,
height-shirtheight-mouthoffset+offsety,
width/2-mouthoffset+offsetx,
height-shirtheight-mouthoffset+offsety
)
}
Since all positional values had an offset x and y, I added a for loop in the draw function that added and removed faces at a rate dependent on variable faceincval limited by variable numfaces.
for(let x = 1; x <=numfaces; x+=1){
drawface(x*10,x*10)
}
numfaces = maxfaces*sin(faceincval)
faceincval+=0.05
The final product looks as follows:
Conclusion:
I had a lot of fun with the dynamics in this assignment, with all the moving parts. I think I was able to create a portrait that is unconventional and a bit unnatural but still represents me on a more metaphorical level.
I found that the code began to get more complicated as I added more pieces, with subtractions from subtractions based on many components quickly began to make less and less sense the more I built. Looking forwards, I’d like to write cleaner code that is more legible and makes more sense to another user.