xxxxxxxxxx
342
// 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 = "lubar";
var nFramesInLoop = 120;
var bEnableExport = true;
var ease = new p5.Ease();
var easingAlgos = ease.listAlgos();
var nAlgos = easingAlgos.length;
var curAlgo;
var curAlgoID;
var nFramesInLoop = 100;
var framesInWaveLoop = nFramesInLoop*6 ; //slow wave pace
// 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;
ship = new Ship();
waves = new Waves();
windo = new PortWindow();
curAlgo = 'doubleExponentialSigmoid'; //'cubicOut';
}
//===================================================
function keyTyped() {
if (bEnableExport) {
if ((key === 'f') || (key === 'F')) {
bRecording = true;
frameRate(2); // while we're exporting
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*6);
} else {
percentCompleteFraction = float(frameCount % (nFramesInLoop*6)) / float(nFramesInLoop*6);
}
// 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";
if (nElapsedFrames % 2 == 0){ // save only every 4 frames
print("Saving output image: " + frameOutputFilename);
saveCanvas(theCanvas, frameOutputFilename, 'png');
}
nElapsedFrames++;
if (nElapsedFrames >= nFramesInLoop*6) {
bRecording = false;
frameRate(60);
}
}
}
//===================================================
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
//----------------------
// Here, I assign some handy variables.
//----------------------
// Here, I use trigonometry to render a rotating element.
// var nFramesInLoop = 100;
// var framesInWaveLoop = nFramesInLoop*6 ; //slow wave pace
//================================================
// curAlgo = 'doubleExponentialSigmoid'; //'cubicOut';
// ship = new Ship();
// waves = new Waves();
// windo = new PortWindow();
background(37, 43, 87) //(39, 24, 71);//(50, 100, 255);
waves.moveWaves();
waves.growWaves();
waves.displayBackground();
ship.tiltShip();
ship.display();
waves.displayForeground();
windo.displayWindow();
}
function Ship() {
this.shipW = 170
this.shipH = 80
this.shipA1 = radians(0);
this.shipA2 = radians(180)
this.goingUnder = false; //true;
this.fangle = TWO_PI;
this.tiltAmt = 0;
this.oinkCount = 0 ;
this.tiltShip = function() {
// print(frameCount, "", this.tiltAmt, "" , this.fangle);
this.oinkCount+=1;
var frameInLoop = frameCount % nFramesInLoop;
var tiltPrct = frameInLoop / nFramesInLoop;
var baseAng = 90;
var deckAng = 90;
// ROCKING SHIP_____________________________________
if (this.goingUnder == false) { //if ship is rocking
this.tiltAmt += 0.1 // add to increase tilt
this.fangle = radians(-this.tiltAmt * sin(tiltPrct * TWO_PI));
if (this.fangle >= radians(40)){//this.tiltAmt > 45) {
this.goingUnder = true;
}
}
//CAPSIZE BOAT____________________________________
if (this.goingUnder) { //rotate ship
// print("aaaah we're sinking")
this.fangle += 0.042//meaning of life
if (this.fangle >= TWO_PI) {
//print(this.oinkCount);
this.oinkCount = 0;
this.tiltAmt = 0;
this.fangle = TWO_PI
this.goingUnder = false;
}}
}
this.display = function() { // build the boat
var tranX = width / 2
var tranY = 60
var mastH = 20
var waterLoop = 0;
fill(220);
push();
translate(tranX, tranY);
rotate(this.fangle); // rotating from center point
translate(0, -40); // better motion
//BUiLD SHIP
//ropes
noFill();
stroke(0);
arc(-30, -90, 65, 50, radians(-5), radians(180 - 60)); //mid to left
arc(-105, -70, 120, 80, radians(0), radians(180 - 80)); // left to nose top
arc(-95, -70, 100, 100, radians(0), radians(180 - 80)); // left to nose bot
arc(42, -90, 80, 80, radians(90), radians(180)); // mid to right top
arc(42, -90, 80, 120, radians(90), radians(180)); // mid to right bot
arc(86, -55, 90, 110, radians(95), radians(180 - 10)); // right base
// masts
arc(2, -100, 0, 200, radians(90), radians(180)); // mast1 mid
arc(-45, 50, 10, 240, radians(270), radians(275)); // mast2 front
arc(40, 50, 10, 200, radians(270), radians(275)); // mast3 back
fill(0);
arc(this.shipW / (-2), 0, 80, 80, radians(180 + 45), radians(180 + 50)); // mast4 nose
// belly
arc(0, 0, this.shipW, this.shipH, this.shipA1, this.shipA2, CHORD); // ship belly
//SAILS
fill(255);
arc(0, -80, 100, 20, radians(20), radians(110)); //sail1
arc(0, -70, 100, 20, radians(20), radians(110)); //sail2
//sail3
pop();
}
}
function Waves() {
this.waveA2 = radians(50)
this.wW = 50;
this.wH = 50;
this.wX = 0;
this.wY = 0;
this.waveStart = -90
this.flipWaves = false;
this.waveIntensityVal = 10;
this.moveWaves = function(offset) {
var frameInLoop = frameCount % nFramesInLoop;//millis()/30%70//frameCount % nFramesInLoop;
var waveFreq = frameInLoop / nFramesInLoop;//frameInLoop / 70//frameInLoop / nFramesInLoop;
var waveStart = offset
this.waveA1 = radians(this.waveIntensityVal * sin(waveFreq * TWO_PI + offset));
}
this.growWaves = function() {
var frameInLoop = frameCount % framesInWaveLoop;
var waveFreq = frameInLoop / framesInWaveLoop;
//referenced from ease examples by Golan
var w01 = waveFreq
var w = (w01 < 0.5) ? (w01 * 2.0) : 2.0 * (1.0 - w01)
var w2 = w
var eased = ease[curAlgo](w2);
var waveIntensity = map(eased, 0, 1, 30, 50);
this.waveIntensityVal = waveIntensity
}
//BACKGROUND WAVES ----------------------------------------------------
this.displayBackground = function() {
translate(0, height / 2);
for (var x = 0; x < width; x += 5) {
var offset = x / 20
this.moveWaves(offset)
noStroke();
fill(0, 10, 200)
arc(x, -10, this.wW, this.wH, this.waveA1 * sin(x * 0.01), this.waveA2);
fill(53, 58, 148);
arc(x, 0, this.wW, this.wH, this.waveA1 * sin(x * 0.02), this.waveA2);
fill(230, 230, 255);
arc(x, 10, this.wW, this.wH, this.waveA1 * sin(x * 0.1), this.waveA2);
fill('black');
arc(x, 25, this.wW * 2, this.wH * 10, this.waveA1 * sin(x * 0.04), this.waveA2);
}
// FOREGROUND WAVES----------------------------------------------------
this.displayForeground = function() {
fill('blue');
for (var x = 0; x < width; x += 5) {
var offset = x / 20
this.moveWaves(offset)
fill('blue');
arc(x, 70, this.wW * 2, this.wH * 5, this.waveA1 * sin(x * 0.01), this.waveA2);
fill(0, 0, 196);
arc(-100 + x, 210, this.wW * 10, this.wH * 5, this.waveA1 * sin(x * 0.02), this.waveA2);
fill(230, 230, 255);
arc(x, 80, this.wW * 2, this.wH * 5, this.waveA1 * sin(x * 0.02), this.waveA2);
fill('black')
arc(x, 90, this.wW * 1.5, this.wH * 5, this.waveA1 * sin(x * 0.1), this.waveA2);
fill(20, 10, 10);
arc(x, 100, this.wW * 2, this.wH * 5, this.waveA1 * sin(x * 0.01), this.waveA2);
fill(0, 0, 196);
arc(-100 + x, 100, this.wW * 7, this.wH * 5, this.waveA1 * sin(x * 0.03), this.waveA2);
}
}
}
}
function PortWindow() {
this.displayWindow = function() {
push();
translate(width / 2, 0);
noFill();
strokeWeight(60);
stroke(10, 7, 1); //inner
arc(0, 0, width - 10, height - 10, 0, 0);
strokeWeight(100);
stroke(77, 60, 17); // 2nd
arc(0, 0, width + 70, height + 70, 0, 0);
strokeWeight(120);
stroke(51, 40, 13);
arc(0, 0, width + 200, height + 200, 0, 0);
stroke(153, 118, 34);
strokeWeight(10);
arc(0, 0, width + 190, height + 190, 0, 0);
arc(0, 0, width + 100, height + 100, 0, 0);
strokeWeight(2);
arc(0, 0, width - 10, height - 10, 0, 0);
stroke(100);
arc(0, 0, width - 65, height - 65, 0, 0);
pop();
}
}