// Template used from 60-212 Website
// This is a template for creating a looping animation in p5.js (JavaScript).
// When you press the 'F' key, this program will export a series of images into
// your default Downloads folder. These can then be made into an animated gif.
// This code is known to work with p5.js version 0.6.0
// Prof. Golan Levin, 28 January 2018
// INSTRUCTIONS FOR EXPORTING FRAMES (from which to make a GIF):
// 1. Run a local server, using instructions from here:
// https://github.com/processing/p5.js/wiki/Local-server
// 2. Set the bEnableExport variable to true.
// 3. Set the myNickname variable to your name.
// 4. Run the program from Chrome, press 'f'.
// Look in your 'Downloads' folder for the generated frames.
// 5. Note: Retina screens may export frames at twice the resolution.
//===================================================
// User-modifiable global variables.
var myNickname = "nickname";
var nFramesInLoop = 120;
var bEnableExport = false;
// Other global variables you don't need to touch.
var nElapsedFrames;
var bRecording;
var theCanvas;
//===================================================
function setup() {
theCanvas = createCanvas(640, 640);
bRecording = false;
nElapsedFrames = 0;
frameRate(120);
}
//===================================================
function keyTyped() {
if (bEnableExport) {
if ((key === 'f') || (key === 'F')) {
bRecording = true;
nElapsedFrames = 0;
}
}
}
//===================================================
function draw() {
// Compute a percentage (0...1) representing where we are in the loop.
var percentCompleteFraction = 0;
if (bRecording) {
percentCompleteFraction = float(nElapsedFrames) / float(nFramesInLoop);
} else {
percentCompleteFraction = float(frameCount % nFramesInLoop) / float(nFramesInLoop);
}
// Render the design, based on that percentage.
// This function renderMyDesign() is the one for you to change.
renderMyDesign (percentCompleteFraction);
// If we're recording the output, save the frame to a file.
// Note that the output images may be 2x large if you have a Retina mac.
// You can compile these frames into an animated GIF using a tool like:
if (bRecording && bEnableExport) {
var frameOutputFilename = myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png";
print("Saving output image: " + frameOutputFilename);
saveCanvas(theCanvas, frameOutputFilename, 'png');
nElapsedFrames++;
if (nElapsedFrames >= nFramesInLoop) {
bRecording = false;
}
}
}
//===================================================
function renderMyDesign (percent) {
//
// THIS IS WHERE YOUR ART GOES.
// This is an example of a function that renders a temporally looping design.
// It takes a "percent", between 0 and 1, indicating where we are in the loop.
// Use, modify, or delete whatever you prefer from this example.
// This example uses several different graphical techniques.
// Remember to SKETCH FIRST!
//----------------------
// here, I set the background and some other graphical properties
background(0);
smooth();
stroke(0, 0, 0);
strokeWeight(0);
//----------------------
// Here, I assign some handy variables.
var cx = 100;
var cy = 100;
//----------------------
// COLOUR NUMBERS FROM BOTTOM
// ORANGE 1
//strokeWeight(0);
//fill(60, 170, 230);
//rect(192, 576, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.9);
eased = (eased + 0.319)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 192, 544);
fill (253, 106, 2);
rect (xPosition1, 576, 32, 32);
// ORANGE 2
//strokeWeight(0);
//fill(60, 170, 230);
//rect(160, 512, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.8);
eased = (eased + 0.45)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 160, 480);
fill (253, 106, 20);
rect (xPosition1, 512, 32, 32);
// ORANGE 3
//strokeWeight(0);
//fill(60, 170, 230);
//rect(128, 448, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.6);
eased = (eased + 0.5)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 128, 480);
fill (253, 106, 2);
rect (xPosition1, 448, 32, 32);
// ORANGE 4
//strokeWeight(0);
//fill(60, 170, 230);
//rect(192, 384, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.4);
eased = (eased + 0.3)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 192, 544);
fill (253, 106, 20);
rect (xPosition1, 384, 32, 32);
// ORANGE 5
//strokeWeight(0);
//fill(60, 170, 230);
//rect(64, 320, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.2);
eased = (eased + 0.66)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 64, 416);
fill (253, 106, 20);
rect (xPosition1, 320, 32, 32);
// ORANGE 6
//strokeWeight(0);
//fill(60, 170, 230);
//rect(128, 256, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.2);
eased = (eased + 0.47)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 128, 480);
fill (253, 106, 20);
rect (xPosition1, 256, 32, 32);
// ORANGE 7
//strokeWeight(0);
//fill(60, 170, 230);
//rect(224, 192, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.4);
eased = (eased + 0.19)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 224, 576);
fill (253, 106, 20);
rect (xPosition1, 192, 32, 32);
// ORANGE 8
//strokeWeight(0);
//fill(60, 170, 230);
//rect(156, 128, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.6);
eased = (eased + 0.39)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 156, 508);
fill (253, 106, 20);
rect (xPosition1, 128, 32, 32);
// ORANGE 9
//strokeWeight(0);
//fill(60, 170, 230);
//rect(32, 64, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.8);
eased = (eased + 0.73)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 32, 384);
fill (253, 106, 20);
rect (xPosition1, 64, 32, 32);
// ORANGE 10
//strokeWeight(0);
//fill(60, 170, 230);
//rect(128, 0, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.9);
eased = (eased + 0.47)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 128, 480);
fill (253, 106, 2);
rect (xPosition1, 0, 32, 32);
push();
translate(320, 320);
var orange = true;
for (var squareX = 0; squareX <= width; squareX += 32){
// Here's a linearly-moving square
var eased = doubleExponentialSigmoid (percent, 0.5);
eased = (eased)%1.0; // shifted by a half-loop, for fun
var yPosition = map(eased, 0, 1, topY, botY);
var rotatingSquareAngle = percent * TWO_PI
rotate(rotatingSquareAngle);
var squareSize = 20;
var topY = 0 - squareSize - 2;
var botY = height + 2;
var sPercent = (percent)%1.0; // shifted by a half-loop
// var yPosition = map(sPercent, 0, 1, topY, botY);
if (orange == true){
fill(253, 106, 2);
orange = false;}
else{
fill(60, 170, 230);
orange = true;}
rect(squareX, yPosition, 20, 20);}
pop();
// BLUE 1
// strokeWeight(0);
// fill(120, 253, 106, 2);
// rect(128, 608, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.2);
eased = (eased + 0.5)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 128, 480);
fill (60, 170, 230);
rect (xPosition1, 608, 32, 32);
// BLUE 2
//strokeWeight(0);
//fill(253, 106, 2);
//rect(64, 544, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.4);
eased = (eased + 0.682)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 64, 416);
fill (60, 170, 230);
rect (xPosition1, 544, 32, 32);
// BLUE 3
//strokeWeight(0);
//fill(253, 106, 2);
//rect(224, 480, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.6);
eased = (eased + 0.23)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 224, 576);
fill (60, 170, 230);
rect (xPosition1, 480, 32, 32);
// BLUE 4
//strokeWeight(0);
//fill(253, 106, 2);
//rect(32, 416, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.8);
eased = (eased + 0.77)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 32, 384);
fill (60, 170, 230);
rect (xPosition1, 416, 32, 32);
// BLUE 5
//strokeWeight(0);
//fill(253, 106, 2);
//rect(160, 352, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.9);
eased = (eased + 0.39)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 160, 512);
fill (60, 170, 230);
rect (xPosition1, 352, 32, 32);
// BLUE 6
//strokeWeight(0);
//fill(253, 106, 2);
//rect(256, 288, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.9);
eased = (eased + 0.115)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 256, 608);
fill (60, 170, 230);
rect (xPosition1, 288, 32, 32);
// BLUE 7
//strokeWeight(0);
//fill(253, 106, 2);
//rect(96, 224, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.8);
eased = (eased + 0.56)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 96, 448);
fill (60, 170, 230);
rect (xPosition1, 224, 32, 32);
// BLUE 8
//strokeWeight(0);
//fill(253, 106, 2);
//rect(64, 160, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.6);
eased = (eased + 0.65)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 64, 416);
fill (60, 170, 230);
rect (xPosition1, 160, 32, 32);
// BLUE 9
//strokeWeight(0);
//fill(253, 106, 2);
// rect(192, 96, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.4);
eased = (eased + 0.284)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 192, 544);
fill (60, 170, 230);
rect (xPosition1, 96, 32, 32);
// BLUE 10
//strokeWeight(0);
//fill(253, 106, 2);
//rect(192, 32, 384, 32);
var eased = doubleExponentialSigmoid (percent, 0.2);
eased = (eased + 0.27)%1.0; // shifted by a half-loop, for fun
var xPosition1 = map(eased, 0, 1, 192, 544);
fill (60, 170, 230);
rect (xPosition1, 32, 32, 32);
push();
translate(320, 320);
var orange = true;
for (var squareX = 0; squareX <= width; squareX += 32){
// Here's a linearly-moving square
var eased = doubleExponentialSigmoid (percent, 0.5);
eased = (eased)%1.0; // shifted by a half-loop, for fun
var yPosition = map(eased, 0, 1, topY, botY);
var rotatingSquareAngle = percent * TWO_PI
rotate(-rotatingSquareAngle);
var squareSize = 20;
var topY = 0 - squareSize - 2;
var botY = height + 2;
var sPercent = (percent)%1.0; // shifted by a half-loop
// var yPosition = map(sPercent, 0, 1, topY, botY);
if (orange == true){
fill(253, 106, 2);
orange = false;}
else{
fill(60, 170, 230);
orange = true;}
rect(squareX, yPosition, 20, 20);}
pop();
}
// Symmetric double-element sigmoid function ('_a' is the slope)
// See https://github.com/IDMNYU/p5.js-func/blob/master/lib/p5.func.js
// From: https://idmnyu.github.io/p5.js-func/
//===================================================
function doubleExponentialSigmoid (_x, _a){
if(!_a) _a = 0.75; // default
var min_param_a = 0.0 + Number.EPSILON;
var max_param_a = 1.0 - Number.EPSILON;
_a = constrain(_a, min_param_a, max_param_a);
_a = 1-_a;
var _y = 0;
if (_x<=0.5){
_y = (pow(2.0*_x, 1.0/_a))/2.0;
}
else {
_y = 1.0 - (pow(2.0*(1.0-_x), 1.0/_a))/2.0;
}
return(_y);
} |