phiaq-Animated Loop

The gif I created went through a couple of revisions because my initial idea was too difficult to create (I was going to have the fox transform into a bear), but I settled on this, which is within my scope. For my gif, rather than exploring different animations, I focused of coding drawing with geometry. I had a lot of fun coding the triangles of the creature and the skull of my creature. I used “adjustable center elliptic window” for the easing function on my paws because I wanted it to be subtle and less dramatic because of the center animal animation. For improvement, I’d like the paws to be moving at a same rate, and I think having a body would improve because it looks awkward moving around. In the future, I want to add more details, complex animations, and colors to the drawing.

Sketches

 

 

Code

 

// This is a template for creating a looping animation in Processing/Java. 
// When you press the 'F' key, this program will export a series of images
// into a "frames" directory located in its sketch folder. 
// These can then be combined into an animated gif. 
// Known to work with Processing 3.3.6
// Prof. Golan Levin, January 2018
// Thanks to Prof. Golan Levin's Processing Animation tempate and Pattern Master 
 
//===================================================
// Global variables. 
String  myNickname = "nickname"; 
int     nFramesInLoop = 300;
int     nElapsedFrames;
boolean bRecording; 
 
//===================================================
void setup() {
  size (600, 600); 
  bRecording = false;
  nElapsedFrames = 0;
}
//===================================================
void keyPressed() {
  if ((key == 'f') || (key == 'F')) {
    bRecording = true;
    nElapsedFrames = 0;
  }
}
 
//===================================================
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } else {
    percentCompleteFraction = (float) (frameCount % nFramesInLoop) / (float)nFramesInLoop;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("frames/" + myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
//===================================================
void renderMyDesign (float percent) {
  //blendMode(SUBTRACT);
  background(0);
 
  //blendMode(DARKEST);
  smooth(); 
  stroke (0, 0, 0); 
  strokeWeight(2);
 
  float size = 350;
  noStroke();
  translate(width/2,(height/2)+50);
 
  //SKULL
  fill(255);
  //ears
 
  ellipse(0,0,size-70,size-70);
  fill(0);
  rect(-size,0,size*2,size);
  fill(255);
  triangle((-size/4.5)-40,0,0,size/3,(size/4.5)+40,0);
  fill(0);
  //eyes
  ellipse(-size/5.5,-size/15,size/4,(size/4)-20);
  ellipse(size/5.5,-size/15,size/4,(size/4)-20);
  fill(60);//inner grey
  ellipse(-size/5.5,-size/15,(size/4)-25,(size/4)-45);
  ellipse(size/5.5,-size/15,(size/4)-25,(size/4)-45);
  fill(120);//most grey 
  ellipse(-size/5.5,-size/15,(size/4)-35,(size/4)-65);
  ellipse(size/5.5,-size/15,(size/4)-35,(size/4)-65);
  //nostrils
  fill(0);
  triangle((-size/6)+40,0,0,(size/6)-30,(size/6)-40,0);
  stroke(255);
  strokeWeight(5);
  line(0,0,0,100);
  //teeth
  stroke(0);
  float nose_len = (size/6)-30;
  float nose_wid = (-size/6)+40;
  line(-nose_wid-20,nose_len+10,-nose_wid-20,(size/6)+10);
  line(-nose_wid-30,nose_len+10,-nose_wid-30,(size/6)+10);
  line(nose_wid+30,nose_len+10,nose_wid+30,(size/6)+10);
 
 
  float pulse = sin(2.0*percent*TWO_PI);
  float opacity = map(pulse,-1,1,255,100);
//FOX
  noStroke();
  float ellipseW = map(pulse,-1,1,size-20,size-30);
  float ellipseH = map(pulse,-1,1,size,size+10);
  fill(230,86,35,opacity);
 
  //semicircle
  pushMatrix();
  rotate(-HALF_PI);
  arc(0, 0, ellipseW, ellipseH,-HALF_PI, HALF_PI);
 
  //black bottom covering 
  fill(0,0,0,opacity);
  popMatrix();
 
  //triangle mouth
  float trix1 = map(pulse,-1,1,-size/3-20,(-size/3)-40);
  float trix3 = map(pulse,-1,1,size/3+20,(size/3)+40);
 
  fill(255,89,18,140);
  triangle(trix1,0,0,size/2.4,trix3,0);
 
  //fill(255,255,255,140);
  //ellipse(0,-size/10,(size/2)+70,(size/2)-100);
  //dark triangle shadow
  fill(184,69,39,opacity);
  triangle(-size/4.5,0,0,size/3,size/4.5,0);
 
  //snout
  fill(20,40,50,opacity);
  triangle(-size/9,0,size/9,0,0,size/9);
 
  //triangle top of nose
  fill(255,255,255,opacity);
  triangle(-size/9,0,0,-size/10,size/9,0);
 
  //eye
  fill(0,0,0,opacity);
  triangle(-size/3,-size/7,-size/6,-size/7,-size/9,-size/13);//left
  triangle(size/9,-size/13,size/6,-size/7,size/3,-size/7);//right
 
  //ears
  //smaller ears
  fill(255,255,255,254);
  triangle(-size/3.6,-size/4,-size/4,-size/1.5,-size/7,-size/4);
  triangle(size/3.6,-size/4,size/4,-size/1.5,size/7,-size/4);
 
  //bigears
  fill(255,102,43,opacity);
  triangle(-size/2.5,-size/4,-size/4,-size/1.3,-size/9,-size/4);
 
  fill(255,102,43,opacity);
  triangle(size/2.5,-size/4,size/4,-size/1.3,size/9,-size/4);
  triangle(size/3,-size/4,size/4,-size/1.5,size/7,-size/4);
 
  //whiskers for right
   strokeWeight(2);
   stroke(255);
   line(size/9,size/11,size/3,size/11);
   line(size/12,size/8,size/4,size/8);
   line(size/8,size/15,size/2.5,size/15);
   //whisker for left
   line(-size/9,size/11,-size/3,size/11);
   line(-size/12,size/8,-size/4,size/8);
   line(-size/8,size/15,-size/2.5,size/15);
   //black mouth
   stroke(0,0,0,opacity);
   line(0,size/9,0,(size/6)+10);//vertical
   line(-size/13,(size/6)+10,size/13,(size/6)+10);
 
    noStroke();
    //left paw skeleton
    line((size/3)+10,size/3,(size/3)+10,size/2);
    line((size/3),size/3,(size/3),size/2);
    line((size/3)-10,size/3,(size/3)-10,size/2);
 
 
    float ease2 = function_AdjustableCenterEllipticWindow(percent,.3);
    float x = map(ease2,0,1,-size/3,(-size/3)+20);
 
 
    fill(255,255,255);
    ellipse(x,size/3,(size/4.5)-20,(size/6)-20);
    ellipse(-x,size/3,(-size/4.5)+20,(size/6)-20);
 
    //right paw skeleton
    strokeWeight(7);
    stroke(0,0,0);
    line((x)+10,size/3,(x)+10,size/2);
    line((x),size/3,(x),size/2);
    line((x)-10,size/3,(x)-10,size/2);
 
    line((-x)+10,size/3,(-x)+10,size/2);
    line((-x),size/3,(-x),size/2);
    line((-x)-10,size/3,(-x)-10,size/2);
 
    //orange paw
    noStroke();
    fill(255,102,43,opacity);
    ellipse(x,size/3,-size/4.5,size/6);
    ellipse(-x,size/3,-size/4.5,size/6);
 
 
 
}
 
 
 
//------------------------------------------------------------------
float function_AdjustableCenterEllipticWindow (float x, float a){
  //functionName = "Adjustable-Center Elliptic Window";
 
  float min_param_a = 0.0 + EPSILON;
  float max_param_a = 1.0 - EPSILON;
  a = constrain(a, min_param_a, max_param_a);
 
  float y = 0;
 
  if (x<=a){
    y = (1.0/a) * sqrt(sq(a) - sq(x-a));
  } 
  else {
    y = (1.0/(1-a)) * sqrt(sq(1.0-a) - sq(x-a));
  }
  return y;
}