conye – Scope
My Praxinoscope depicts Pacman eating! I spent the majority of the time testing out different functions from Golan’s Pattern Master. I tried to get the main circle shape to shrink and grow during the loop to make the transitions smoother, but I’m not convinced that it looks as good on paper/code as it looked in my head because my mind doesn’t have the physical frame restrictions that this Praxinoscope does, which I should have considered. I still had fun picking and choosing easing functions though!
Here’s a rough gif of the result!
This is a link to the praxinoscope-output pdf.
Here is the code. The majority of it is Golan Levin’s template, but my code is under “myfunct()”.
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; //------------------------------------------------------- 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); myfunct(whichFrame); popMatrix(); } myFrameCount++; } //this is mine void myfunct(int whichFrame){ fill(0); if(whichFrame == 4|| whichFrame == 5 || whichFrame == 7 || whichFrame == 8){ ellipse(map(function_ParabolaThroughAPoint(whichFrame/10.0, 0.833, 0.643), 0, 1, -12, 27), 0, 20*function_TukeyWindow(whichFrame/10.0, 0.45), 20*function_TukeyWindow(whichFrame/10.0, 0.45)); } else{ arc(map(function_ParabolaThroughAPoint(whichFrame/10.0, 0.833, 0.643), 0, 1, -12, 27), 0, 20*function_TukeyWindow(whichFrame/10.0, 0.45), 20*function_TukeyWindow(whichFrame/10.0, 0.45), QUARTER_PI, (2*PI - QUARTER_PI)); } if(whichFrame < 4 ) {ellipse(2, 0, 5, 5);} if(whichFrame <8 ){ellipse(12, 0, 5, 5);} } float function_AdjustableCenterHyperellipticWindow (float x, float a, int n){ 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; float pwn = n * 2.0; if (x<=a){ y = (1.0/a) * pow( pow(a, pwn) - pow(x-a, pwn), 1.0/pwn); } else { y = ((1.0/ (1-a))) * pow( pow(1.0-a, pwn) - pow(x-a, pwn), 1.0/pwn); } return y; } float function_ParabolaThroughAPoint (float x, float a, float b){ float min_param_a = 0.0 + EPSILON; float max_param_a = 1.0 - EPSILON; float min_param_b = 0.0; float max_param_b = 1.0; a = constrain(a, min_param_a, max_param_a); b = constrain(b, min_param_b, max_param_b); float A = (1-b)/(1-a) - (b/a); float B = (A*(a*a)-b)/a; float y = A*(x*x) - B*(x); y = constrain(y, 0,1); return y; } float function_TukeyWindow (float x, float a) { float ah = a/2.0; float omah = 1.0 - ah; float y = 1.0; if (x <= ah) { y = 0.5 * (1.0 + cos(PI* ((2*x/a) - 1.0))); } else if (x > omah) { y = 0.5 * (1.0 + cos(PI* ((2*x/a) - (2/a) + 1.0))); } return y; } |