nixel-Scope

 

pdf: zoetrope-output

For my zoetrope design, I experimented a lot with arcs. I started off with just one eye because I wanted to make some sort of illuminati related loop, but then decided to go in a simpler direction. I like the result, although I wish there was more time to make the animation actually loop instead of clearly starting over every time.

Here are some very rough initial designs. My first idea was a jump roping ball. Second was a blinking eye looking around. I initially programmed this one using ellipses but was not satisfied so I switched to arcs and got the final result you see.

 
// Processing Template for Zoetrope toy by Eye Think
// https://www.amazon.com/Zoetrope-Animation-Toy-Victorian-Illusion/dp/B007VM9HZO/
// Developed for Processing 3.3.6 * http://processing.org
// 24 January 2018 * Golan Levin 
 
// See information about Processing PDF export at: 
// https://processing.org/reference/libraries/pdf/index.html
// PDF generated by Processing can be opened in Adobe Illustrator.
import processing.pdf.*;
boolean bRecordingPDF = false;
 
float inch = 72; 
float paperStripWidth = inch * 12.625;
float paperStripHeight = inch * 1.3125;
float overlapMargin = inch * 0.4375;
float artAreaWidth = paperStripWidth - overlapMargin;
float artAreaHeight = paperStripHeight;
 
final int nFrames = 11; 
int myFrameCount = 0;
int exportFrameCount = 0; 
boolean bAnimate = true; 
boolean bExportFrameImages = false;
 
//-------------------------------------------------------
void setup() {
  size(1224, 792); // 17x11" at 72DPI
  frameRate(15);
  smooth();
} 
 
//-------------------------------------------------------
void draw() {
  background(240); 
  if (bRecordingPDF) {
    beginRecord(PDF, "zoetrope-output.pdf");
  }
 
  // Do all the drawing. 
  pushMatrix(); 
  translate(width/2, height/2);
  translate(0-paperStripWidth/2, 0-paperStripHeight/2); 
 
  drawCutLines(); 
  drawGuides(); 
  drawAllFrames();
  popMatrix();
 
  if (bExportFrameImages) {
    // If activated, export .PNG frames 
    if (exportFrameCount < nFrames) {
      String filename = "frame_" + nf((exportFrameCount%nFrames), 3) + ".png";
      saveFrame("frames/" + filename);
      println("Saved: " + filename); 
      exportFrameCount++;
      if (exportFrameCount >= nFrames) {
        bExportFrameImages = false;
        exportFrameCount = 0;
      }
    }
  }
 
  if (bRecordingPDF) {
    endRecord();
    bRecordingPDF = false;
  }
}
 
 
//-------------------------------------------------------
void keyPressed() {
  switch (key) {
  case ' ': 
    // Press spacebar to pause/unpause the animation. 
    bAnimate = !bAnimate;
    break;
 
  case 'p': 
  case 'P':
    // Press 'p' to export a PDF for the Zoetrope. 17x11" paper!
    bRecordingPDF = true; 
    break;
 
  case 'f': 
  case 'F': 
    // Press 'f' to export .png Frames (to make an animated .GIF)
    myFrameCount = 0; 
    exportFrameCount = 0; 
    bExportFrameImages = true;
    bAnimate = true; 
    break;
  }
}
 
//-------------------------------------------------------
void drawCutLines() {
  fill(0); 
  textAlign(CENTER, BOTTOM); 
  text("Zoetrope Template", paperStripWidth/2, -20); 
 
  stroke(0); 
  strokeWeight(1.0);
  noFill(); 
  if (!bRecordingPDF) {
    fill(255);
  }
  rect(0, 0, paperStripWidth, paperStripHeight);
}
 
//-------------------------------------------------------
void drawGuides() {
  // This function draws the guidelines. 
  // Don't draw these when we're exporting the PDF. 
  if (!bRecordingPDF) {
    float frameSpacing = artAreaWidth / nFrames;
 
    stroke(128); 
    strokeWeight(0.2);
    for (int i=0; i<nFrames; i++) {
      pushMatrix();
      translate(i * frameSpacing, 0);
      rect(0, 0, frameSpacing, artAreaHeight); 
      popMatrix();
    }
  }
}
 
//-------------------------------------------------------
void drawAllFrames() {
  for (int i=0; i<nFrames; i++) {
 
    float frameSpacing = artAreaWidth / nFrames;
 
    pushMatrix();
    translate((i + 0.5) * frameSpacing, 0);
 
    int whichFrame = i; 
    if (bAnimate) {
      whichFrame = (i+myFrameCount)%nFrames;
    }
     drawArtFrame (whichFrame); 
 
 
    popMatrix();
  }
  myFrameCount++;
}
 
 
 
//-------------------------------------------------------
//thank you to golan for the template and examples
void drawArtFrame(int whichFrame) { 
 
  noFill();
  strokeWeight(2);
  stroke(0,0,0);
  float eyeY = map(whichFrame, 0, nFrames-1, 0, artAreaHeight*0.30);
  float eyeLid = map(whichFrame, 0, nFrames-1, artAreaHeight*0.30, 0);
  float irisY = map(whichFrame, 0, nFrames-1, 0, artAreaHeight*0.15);
  float eyebrow = map(whichFrame, 0, nFrames-1, 0, artAreaHeight*0.1);
  float tearY = map(whichFrame, 0, nFrames-1, artAreaHeight*0.7, artAreaHeight*1.1);
  float tearY2 = map(whichFrame, 0, nFrames-1, artAreaHeight*0.9, artAreaHeight*1.2);
 
  //right eye
  fill(255,255,255);
  stroke(0,0,0);
  arc(20, artAreaHeight/2, 30, eyeY, 0, PI);
  stroke(50,100,200);
  strokeWeight(2);
  fill(0,0,0);
  arc(20, artAreaHeight/2+1, 15, irisY, 0, PI);
  stroke(0,0,0);
  strokeWeight(3);
  fill(255,255,255);
  arc(20, artAreaHeight/2-1, 30, eyeLid, 0, PI);
 
 
  //left eye
  fill(255,255,255);
  stroke(0,0,0);
  arc(-20, artAreaHeight/2, 30, eyeY, 0, PI);
  stroke(50,100,200);
  strokeWeight(2);
  fill(0,0,0);
  arc(-20, artAreaHeight/2+1, 15, irisY, 0, PI);
  stroke(0,0,0);
  strokeWeight(3);
  fill(255,255,255);
  arc(-20, artAreaHeight/2-1, 30, eyeLid, 0, PI);
 
  //eyebrows
  strokeWeight(2);
  line(7, -eyebrow+40, 35, 40);
  line(-35, 40, -7, -eyebrow+40);
 
  //sad water
  fill(10,50,200,whichFrame*0.9+200);
  noStroke();
  ellipse(-25, tearY, 2, 10);
  ellipse(-25, tearY2, 2, 10);
}