xxxxxxxxxx
293
/*
// 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 p5.js, September 2018 * Golan Levin
*/
var inch = 72.0;
var diamArtInner = inch * 1.50;
var diamArtOuter = inch * 4.80;
var diamCutInner = inch * 1.41;
var diamCutOuter = inch * 4.875;
var holeDy = inch * 0.23;
var holeDx = inch * 0.20;
var holeD = inch * 0.1;
var nFrames = 10;
var myFrameCount = 0;
var exportFrameCount = 0;
var bAnimate = true;
var bExportFrameImages = false;
var bRecordingSinglePNG = false;
//-------------------------------------------------------
function setup() {
createCanvas(792, 612); // 11x8.5" at 72DPI
frameRate(20);
smooth();
}
//-------------------------------------------------------
function draw() {
background(240);
// Do all the drawing.
push();
translate(width/2, height/2);
drawCutLines();
drawGuides();
drawAllFrames();
pop();
if (bExportFrameImages){
// Note that myFrameCount is incremented elsewhere.
var filename = "myZoetrope_" + nf(myFrameCount,2) + ".png";
saveCanvas(filename, 'png');
if (myFrameCount >= nFrames){
bExportFrameImages = false;
}
}
if (bRecordingSinglePNG) {
saveCanvas('myPraxinoscope.png', 'png');
bRecordingSinglePNG = false;
}
}
//-------------------------------------------------------
function keyPressed() {
switch (key) {
case ' ':
// Press spacebar to pause/unpause the animation.
bAnimate = !bAnimate;
break;
case 'p':
case 'P':
// Press 'p' to export a single PNG for the Zoetrope.
// Note: This is for 17x11" paper!
// Be sure to print at 100%!
bRecordingSinglePNG = true;
break;
case 'f':
case 'F':
// Press 'f' to export multiple frames
// (in order to make an animated .GIF)
// such as with http://gifmaker.me/
myFrameCount = 0;
exportFrameCount = 0;
bExportFrameImages = true;
bAnimate = true;
break;
}
}
//-------------------------------------------------------
function drawCutLines() {
fill(0);
textAlign(CENTER, BOTTOM);
text("Praxinoscope Template", 0, 0-diamCutOuter/2-6);
stroke(0);
strokeWeight(1.0);
noFill();
if (!bRecordingSinglePNG) {
fill(255);
}
ellipse(0, 0, diamCutOuter, diamCutOuter);
noFill();
if (!bRecordingSinglePNG) {
fill(240);
}
ellipse(0, 0, diamCutInner, diamCutInner);
noFill();
ellipse(diamCutOuter/2 - holeDx, 0-holeDy, holeD, holeD);
line (diamCutInner/2, 0, diamCutOuter/2, 0);
}
//-------------------------------------------------------
function drawGuides() {
// This function draws the guidelines.
// Don't draw these when we're exporting the PNG.
if (!bRecordingSinglePNG) {
noFill();
stroke(128);
strokeWeight(0.2);
ellipse(0, 0, diamArtInner, diamArtInner);
ellipse(0, 0, diamArtOuter, diamArtOuter);
for (var i=0; i<nFrames; i++) {
var angle = map(i, 0, nFrames, 0, TWO_PI);
var pxi = diamArtInner/2 * cos(angle);
var pyi = diamArtInner/2 * sin(angle);
var pxo = diamArtOuter/2 * cos(angle);
var pyo = diamArtOuter/2 * sin(angle);
stroke(128);
strokeWeight(0.2);
line (pxi, pyi, pxo, pyo);
}
// Draw the red wedge outline, highlighting the main view.
var redWedge = 7; // assuming nFrames = 10
for (var i=redWedge; i<=(redWedge+1); i++) {
var angle = map(i, 0, nFrames, 0, TWO_PI);
var pxi = diamArtInner/2 * cos(angle);
var pyi = diamArtInner/2 * sin(angle);
var pxo = diamArtOuter/2 * cos(angle);
var 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);
var startAngle = redWedge*TWO_PI/nFrames;
var endAngle = (redWedge+1)*TWO_PI/nFrames;
arc(0, 0, diamArtInner, diamArtInner, startAngle, endAngle);
arc(0, 0, diamArtOuter, diamArtOuter, startAngle, endAngle);
for (var i=0; i<nFrames; i++) {
var angle = map(i, 0, nFrames, 0, TWO_PI);
push();
rotate(angle);
var 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);
pop();
}
}
}
//-------------------------------------------------------
function drawAllFrames() {
for (var i=0; i<nFrames; i++) {
var angle = map(i, 0, nFrames, 0, TWO_PI);
var originY = ((diamArtOuter + diamArtInner)/2)/2;
push();
rotate(angle);
translate(0, 0-originY);
scale(0.8, 0.8); // feel free to ditch this
var whichFrame = i;
if (bAnimate) {
whichFrame = (i+myFrameCount)%nFrames;
}
drawArtFrame (whichFrame);
// drawArtFrameAlternate (whichFrame);
pop();
}
myFrameCount++;
}
//-------------------------------------------------------
function drawArtFrame ( 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, 0, -45);
// Draw a pulsating ellipse
noFill();
stroke(0);
strokeWeight(1);
var t = map(whichFrame, 0, nFrames, 0, 1);
var diam = map(cos(t*TWO_PI), -1, 1, 25, 50);
ellipse(0, -45, diam, diam*0.8);
// Draw some expanding boxes, centered on the local origin
var nBoxes = 3;
for (var i=0; i<nBoxes; i++) {
var F = ((whichFrame + i*nFrames)/(1.0*nBoxes))%nFrames;
var rs = map(F, 0, nFrames-1, 0, 35);
var rx = 0;
var ry = 0;
var rg = map(F, 0, nFrames, 0, 255);
stroke(rg);
strokeWeight(1.0);
rect(rx-rs/2, ry-rs/2, rs, rs);
}
// Draw some rotating spokes
var nSpokes = 7;
for (var i=0; i<nSpokes; i++) {
var cx = 0;
var cy = 45;
var u = 0 - map(whichFrame + i*nFrames, 0, nFrames*nSpokes, 0, 1);
var sx = cx + 15 * cos(u * TWO_PI);
var sy = cy + 15 * sin(u * TWO_PI);
stroke(0);
strokeWeight(1);
line (cx, cy, sx, sy);
}
}
//-------------------------------------------------------
function drawArtFrameAlternate( whichFrame ) {
// An alternate drawing test.
// Draw a falling object.
// Draw a little splat on the frame when it hits the ground.
if (whichFrame == (nFrames-1)) {
stroke(0, 0, 0);
strokeWeight(0.5);
var nL = 10;
for (var i=0; i<nL; i++) {
var a = HALF_PI + map(i, 0, nL-1, 0, TWO_PI);
var cx = 12 * cos(a);
var cy = 10 * sin(a);
var dx = 16 * cos(a);
var dy = 13 * sin(a);
line (cx, 45+cy, dx, 45+dy);
}
}
// Draw a little box frame
fill(255);
stroke(0, 0, 0);
strokeWeight(1);
rect(-5, -50, 10, 100);
// Make the puck accelerate downward
var t = map(whichFrame, 0, nFrames-1, 0, 1);
var t2 = pow(t, 2.0);
var rh = 8 + whichFrame * 0.5; // wee stretch
var ry = map(t2, 0, 1, 0, 100-rh) - 50;
noStroke();
fill(0, 0, 0);
rect(-5, ry, 10, rh);
}