ango-Scope

praxinoscope-output

// Template for KidzLabs/4M/Toysmith Animation Praxinoscope
// https://www.amazon.com/4M-3474-Animation-Praxinoscope/dp/B000P02HYC
// https://www.walmart.com/ip/Animation-Praxinoscope-Science-Kits-by-Toysmith-3474/45681503
// Developed for Processing 3.3.6 * http://processing.org
// 23 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 diamArtInner = inch * 1.50;
float diamArtOuter = inch * 4.80;
float diamCutInner = inch * 1.41;
float diamCutOuter = inch * 4.875;
float holeDy = inch * 0.23;
float holeDx = inch * 0.20;
float holeD = inch * 0.1;
 
final int nFrames = 10;
int myFrameCount = 0;
int exportFrameCount = 0;
boolean bAnimate = true;
boolean bExportFrameImages = false;
 
float angle = 10;
 
//-------------------------------------------------------
void setup() {
size(792, 612); // 11x8.5" at 72DPI
frameRate(15);
smooth();
}
 
//-------------------------------------------------------
void draw() {
background(240);
if (bRecordingPDF) {
beginRecord(PDF, "praxinoscope-output.pdf");
}
 
// Do all the drawing.
pushMatrix();
translate(width/2, height/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 Praxinoscope.
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("Praxinoscope Template", 0, 0-diamCutOuter/2-6);
 
stroke(0);
strokeWeight(1.0);
 
noFill();
if (!bRecordingPDF) {
fill(255);
}
ellipse(0, 0, diamCutOuter, diamCutOuter);
 
noFill();
if (!bRecordingPDF) {
fill(240);
}
ellipse(0, 0, diamCutInner, diamCutInner);
 
noFill();
ellipse(diamCutOuter/2 - holeDx, 0-holeDy, holeD, holeD);
 
line (diamCutInner/2, 0, diamCutOuter/2, 0);
}
 
//-------------------------------------------------------
void drawGuides() {
// This function draws the guidelines.
// Don't draw these when we're exporting the PDF.
if (!bRecordingPDF) {
 
noFill();
stroke(128);
strokeWeight(0.2);
ellipse(0, 0, diamArtInner, diamArtInner);
ellipse(0, 0, diamArtOuter, diamArtOuter);
 
for (int i=0; i<nFrames; i++) {
float angle = map(i, 0, nFrames, 0, TWO_PI);
float pxi = diamArtInner/2 * cos(angle);
float pyi = diamArtInner/2 * sin(angle);
float pxo = diamArtOuter/2 * cos(angle);
float pyo = diamArtOuter/2 * sin(angle);
stroke(128);
strokeWeight(0.2);
line (pxi, pyi, pxo, pyo);
}
 
// Draw the red wedge outline, highlighting the main view.
int redWedge = 7; // assuming nFrames = 10
for (int i=redWedge; i<=(redWedge+1); i++) {
float angle = map(i, 0, nFrames, 0, TWO_PI);
float pxi = diamArtInner/2 * cos(angle);
float pyi = diamArtInner/2 * sin(angle);
float pxo = diamArtOuter/2 * cos(angle);
float pyo = diamArtOuter/2 * sin(angle);
stroke(255, 0, 0);
strokeWeight(2.0);
line (pxi, pyi, pxo, pyo);
}
noFill();
stroke(255, 0, 0);
strokeWeight(2.0);
float startAngle = redWedge*TWO_PI/nFrames;
float endAngle = (redWedge+1)*TWO_PI/nFrames;
arc(0, 0, diamArtInner, diamArtInner, startAngle, endAngle);
arc(0, 0, diamArtOuter, diamArtOuter, startAngle, endAngle);
 
for (int i=0; i<nFrames; i++) {
float angle = map(i, 0, nFrames, 0, TWO_PI);
 
pushMatrix();
rotate(angle);
float originY = ((diamArtOuter + diamArtInner)/2)/2;
translate(0, 0-originY);
 
noFill();
stroke(128);
strokeWeight(0.2);
line (-inch/2, 0, inch/2, 0);
line (0, -inch/2, 0, inch/2);
 
popMatrix();
}
}
}
 
//-------------------------------------------------------
void drawAllFrames() {
for (int i=0; i<nFrames; i++) {
float angle = map(i, 0, nFrames, 0, TWO_PI);
float originY = ((diamArtOuter + diamArtInner)/2)/2;
 
pushMatrix();
rotate(angle);
translate(0, 0-originY);
scale(0.8, 0.8); // feel free to ditch this
 
int whichFrame = i;
if (bAnimate) {
whichFrame = (i+myFrameCount)%nFrames;
}
drawArtFrame (whichFrame);
// drawArtFrameAlternate (whichFrame);
 
popMatrix();
}
myFrameCount++;
}
 
//-------------------------------------------------------
void drawArtFrame (int whichFrame) {
// Draw the artwork for a generic frame of the Praxinoscope,
// given the framenumber (whichFrame) out of nFrames.
// NOTE #1: The "origin" for the frame is in the center of the wedge.
// NOTE #2: Remember that everything will appear upside-down!
 
// Draw the frame number
fill(0);
noStroke();
textAlign(CENTER, CENTER);
text (whichFrame, -1, -47);
 
// Draw a pulsating ellipse
noFill();
stroke(0);
strokeWeight(1);
float t = map(whichFrame, 0, nFrames, 0, 1);
float diam = map(cos(t*TWO_PI), -1, 1, 0, 50);
float y = map(sin(t*PI), -1, 1, 0, 50);
int nEllipseBoys = 1;
for (int i=0; i<nEllipseBoys; i++) {
//float F = ((whichFrame + i*nFrames)/(float)nEllipseBoys)%nFrames;
//float rg = map(F, 0, nFrames, 0, 255);
//fill(rg);
//ellipse(0, y, diam, y);
 
// Draw some expanding ELLIPSES, centered on the local origin
int nEllipses = 1;
for (int j=0; j<nEllipses; j++) {
float P = ((whichFrame + j*nFrames)/(float)nEllipses)%nFrames;
float rs = map(P, 0, nFrames-1, 0, 55);
float rx = 0;
float ry = 0;
float yay = map(P, 0, nFrames, 0, 255);
fill(yay);
 
//ellipse(rx-rs/2, ry-rs/2, rs, rs);
//ellipse(rx-rs/2, ry+rs/2, rs, rs);
//ellipse(rx+rs/2, ry+rs/2, rs, rs);
//ellipse(rx+rs/2, ry-rs/2, rs, rs);
 
pushMatrix();
rectMode(CENTER);
translate(rx, rx);
rotate(angle * 3);
rect(0, 0, 52, 52);
angle = angle + 0.02;
popMatrix();
 
pushMatrix();
rectMode(CENTER);
translate(rx, rx);
rotate(angle * 2);
fill(yay * 6);
rect(0, 0, 35, 35);
angle = angle + 0.02;
popMatrix();
 
pushMatrix();
rectMode(CENTER);
translate(rx, rx);
rotate(angle);
fill(yay);
rect(0, 0, 20, 20);
angle = angle + 0.02;
popMatrix();
 
}
}
}