weirdie-AnimatedLoop

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;
}