My initial inspiration for the piece was simply thinking about how objects could visually track movement, and because I'm me I wanted to do that in kind of a weird way. The first step was creating the eyes that would be able to track movement, initially using the mouse for testing. After that, I tried a bunch of functions to find a path for the fly that I liked, eventually picking a 3-petaled polar graph "flower" because of the way it looped around 3 of the eyes. Getting the fly to face the direction it was traveling was a little tricky, as that involved calculating the direction of the next frame of the fly and rotating it towards that. I chose the Double Exponential Ogee function because I wanted the fly to slow down slightly going around corners, and speed up when it was traveling in more of a straight line, and the Ogee function had that pattern - fast, slow, fast - and so I used that while phase-shifting it a bit. Overall, I'm pretty pleased with the result, as I came pretty close to that concept that I had in mind and I learned a lot about mapping and direction changes in the process. I initially thought about having some of the eyes blink randomly or blink in response to the fly coming too close. However, with the short length of the GIF I chose not too, but it could be something to try in the future. I also think the addition of motion blur to the fly would have made the appearance more smooth.
Sketches:
Code:
function renderMyDesign(percent) { // here, I set the background background(255, 147, 140); smooth(); // coordinates of the fly var flyx = 0; var flyy = 0; var p = map(percent, 0, 1, 0, 3.14); if(percent >=0 && percent <= 0.3333) { var frac = map(percent, 0, 0.3333, 0, 1); var speed = function_DoubleExponentialOgee(frac, 0.15); p = map(speed, 0, 1, 0, PI/3); } else if(percent > 0.333 && percent <= 0.666) { var frac = map(percent, 0.3333, 0.666, 0, 1); var speed = function_DoubleExponentialOgee(frac, 0.15); p = map(speed, 0, 1, PI/3, 2*PI/3); } else { var frac = map(percent, 0.666, 1, 0, 1); var speed = function_DoubleExponentialOgee(frac, 0.15); p = map(speed, 0, 1, 2*PI/3, PI); } var r = cos(3*(p+PI/2)); var nr = cos(3*(p+0.0157+PI/2)); var jousx = map(r*cos((p+PI/3+PI/2)), -1, 1, 30, 630); var jousy = map(r*sin((p+PI/3+PI/2)), -1, 1, 30, 630); var nextx = map(nr*cos((p+0.0157 + PI/3+PI/2)), -1, 1, 30, 630); var nexty = map(nr*sin((p+0.0157 + PI/3+PI/2)), -1, 1, 30, 630); var jx = map(jousx, 30, 630, -1, 1); var jy = map(jousy, 30, 630, -1, 1); var nx = map(nextx, 30, 630, -1, 1); var ny = map(nexty, 30, 630, -1, 1); var direction = atan2((ny - jy), (nx - jx)) + PI/2.2; flyx = jousx; flyy = jousy; //eyeballs!!! noStroke(); for (var r = 0; r < 5; r++) { for (var c = 0; c < 4; c++) { var midx = 0; var midy = 0; if (r % 2 == 0) { midx = 106.66 + c * 213.33; midy = 160 * r; } else { midx = 213.333 * c; midy = 160 * r } //direction of the fly var fx = map(flyx, 0, width, -1, 1); var fy = map(flyy, 0, height, -1, 1); var mx = map(midx, 0, width, -1, 1); var my = map(midy, 0, height, -1, 1); var dir = atan2((fy - my), (fx - mx)); var amp = 30; if (dist(midx, midy, flyx, flyy) <= 30) amp = dist(midx, midy, flyx, flyy); //white of eye fill(244, 244, 233); ellipse(midx, midy, 130, 130); push(); translate(midx + amp * cos(dir), midy + amp * sin(dir)); rotate(dir); //distortion value var d = constrain(dist(midx, midy, flyx, flyy), 0, 30); var squish = map(d, 0, 30, 1, 0.9); //cornea stroke(20, 114, 80); strokeWeight(3); fill(61, 249, 187); ellipse(0, 0, 70 * squish, 70); noStroke(); //pupil fill(19, 20, 45); ellipse(0, 0, 30 * squish, 30); pop(); } } push(); fill(19, 20, 45); translate(flyx, flyy); rotate(direction); stroke(19, 20, 45); strokeWeight(1.5); ellipse(0, 0, 20, 30); ellipse(0, -15, 16, 10); line(0, 0, -17, -17); line(0, 0, 17, -17); line(-17, -17, -20, -15); line(17, -17, 20, -15); line(0, -10, 17, 3); line(0, -10, -17, 3); line(17, 3, 20, 6); line(-17, 3, -20, 6); line(0, 0, 17, 17); line(0, 0, -17, 17); fill(255, 89, 0); noStroke(); ellipse(6, -17, 6, 8); ellipse(-6, -17, 6, 8); fill(160, 255, 223, 150); beginShape(); vertex(0, -10); vertex(-15, 0); vertex(-15, 25); vertex(-4, 15); vertex(0, -10); endShape(); beginShape(); vertex(0, -10); vertex(15, 0); vertex(15, 25); vertex(4, 15); vertex(0, -10); endShape(); pop(); } // Double Exponential Ogee function ('_a' is the slope) //(it goes fast, slowwww, fast) // See https://github.com/IDMNYU/p5.js-func/blob/master/lib/p5.func.js // From: https://idmnyu.github.io/p5.js-func/ //=================================================== function function_DoubleExponentialOgee (x, a){ functionName = "Double-Exponential Ogee"; var min_param_a = 0.0 + Number.EPSILON; var max_param_a = 1.0 - Number.EPSILON; a = constrain(a, min_param_a, max_param_a); var y = 0; if (x<=0.5){ y = (pow(2.0*x, 1.0-a))/2.0; } else { y = 1.0 - (pow(2.0*(1.0-x), 1.0-a))/2.0; } return y; } |