/*
// 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 bRecordingPNG = false;
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;
//-------------------------------------------------------
function setup() {
createCanvas(792, 612); // 11x8.5" at 72DPI
frameRate(20);
smooth();
}
//-------------------------------------------------------
function draw() {
background(255);
// Do all the drawing.
push();
translate(width/2, height/2);
drawCutLines();
//drawGuides();
drawAllFrames();
pop();
if (bRecordingPNG) {
saveCanvas('myPraxinoscope.png', 'png');
bRecordingPNG = 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 PNG for the Praxinoscope.
bRecordingPNG = 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;
if (bExportFrameImages) {
var recordFramerate = 1.0;
var recordDuration = nFrames * 1.01;
frameRate(recordFramerate); // 1 FPS baby
saveFrames('Praxinoscope_', 'png', recordDuration, recordFramerate);
bExportFrameImages = false;
}
break;
}
}
//-------------------------------------------------------
function drawCutLines() {
fill(0);
textAlign(CENTER, BOTTOM);
text("Praxinoscope Template", 0, 0-diamCutOuter/2-6);
stroke(0);
strokeWeight(1.0);
noFill();
if (!bRecordingPNG) {
fill(255);
}
ellipse(0, 0, diamCutOuter, diamCutOuter);
noFill();
if (!bRecordingPNG) {
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 (!bRecordingPNG) {
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 ) {
//ellipses
fill(random(0, 255), random(150,200), random(200,230));
stroke(255);
strokeWeight(2);
for (var i = 0; i < nFrames; i++)
{
var t = map(whichFrame, 1, nFrames, 1, i*.38);
var diam = map(cos(t*TWO_PI*.22), -1, 1, -i*8, i*8);
ellipse(0,i*7-10,diam*.7,diam*0.4);
}
//lines
p1 = -45;
p2 = 70;
p3 = -0;
p4 = 54;
stroke(100);
strokeWeight(1.2);
line2 = map(whichFrame, -1, 1, -50, 50);
for (var i = 0; i < nFrames; i++) {
line(p1+8*whichFrame,p2,p3,p4);
}
//triangles
var p1x = 50;
var p1y = -25;
var p2x = 60;
var p2y = -60;
var p3x = -40;
var p3y = -10;
strokeWeight(2);
stroke(255);
for (var i = 0; i < nFrames; i++) {
fill(25*whichFrame);
triangle(p1x/(whichFrame*-1)-10, p1y-40, p2x/(whichFrame**2)+20, p2y+20, p3x+whichFrame*10, p3y);
fill(30*whichFrame);
triangle(p1x/(whichFrame*2)-3, p1y-30, p2x/(whichFrame)+20, p2y+20, p3x+whichFrame*-2+15, p3y);
}
//circles
var p1 = -50;
var p2 = 0;
noFill();
stroke(50);
strokeWeight(1);
for (var i = 0; i < nFrames-4; i+=2) {
stroke(2**whichFrame);
ellipse(p1-whichFrame*5, p2+20, 10, 10);
p1 = 0;
p2 = 0;
}
} |