Sepho – Clock

For my clock I chose to create a clock that doesn't tell people what time it is, it tells people what time it 'feels like.' When planning for this project I began thinking a lot on how weirdly arbitrary and meaningless measuring time really was. It was interesting to think of how we need this abstraction of miscellaneous systems such as the earths rotation to keep order in our lives. What interested me the most about our measurements of time was how absent subjectivity and the humanistic experience of time were from these measurements. With my clock my goal was to subvert the objective, factual nature of "clock" and how we view it. Suddenly time is something subjective and fickle with absolutely no foundations in reality.

For my process I really wanted to keep the actual clock pretty simple and let the idea do the talking, and I learned that for me, keeping things simple is the most complex thing ever. In order to replicate the face of a digital clock I had to draw my own font out of shapes and in order to get the average between times I needed to convert times to degrees on a circle.

Ideally, this clock would exist as any other clock would, for example as a simply alarm clock on a night-stand. I really enjoy the idea of taking something so personal such as what time it "feels" and presenting as fact by putting it on a clock.

yuvian-clock

new clock

For my first clock, I chose to represent time in a way similar to that of a normal clock. With a familiar elliptical shape, I used three rings to represent the hour, minute, and second. According to the time, I placed dots along the three rings which are evenly divided between the 360 degrees of a circle. Because it may get hard to read at times, I also added a feature that would allow the user to see the actual time when they move their mouse over the center of the clock. Afterwards, I added some styling to the clock - namely, the grey ring and circle to help differentiate between hours, minutes, and seconds.

//60212 CLOCK SKETCH

var h, m, s;

function setup() {
  createCanvas(500,500);
}

function draw() {
  background(0);
  
  h = hour();
  m = minute();
  s = second();
  
  ellipseMode(CENTER);
  
  //white circle bg for hours
  stroke(90);
  noFill();
  strokeWeight(15)
  ellipse(width/2,height/2, 380)
  
  
  //grey circle bg for seconds
  fill(30);
  noStroke();
  ellipse(width/2,height/2, 200,200)
  
  if (mouseX > 200 && mouseX < 300 && mouseY > 200 && mouseY < 300) {
    displayTime();
  }
  
  push();
    translate(width/2, height/2);
    angleMode(DEGREES)
    rotate(-90)
    dotSize = 3;
    noStroke();
    ///////////////////////////////////
    var hRad = 190;
    // var hColor = map(h,0,23,50,255);
    var hColor = color(0)
    // var hColor = color(226, 9, 63)
    var hDotSize = 5;
    fill(hColor);
    for (var i = 0; i <= 360; i+= 360/h) {
			if (h == 0) {
				h = 12
			} else {
				ellipse(cos(i) * hRad, sin(i) * hRad,hDotSize,hDotSize);
			}
      
    }
    ///////////////////////////////////
    var mRad = 130;
    var mColor = map(m,0,59,50,255);
    // var mColor = color(53, 87, 255)
    fill(mColor);
    for (var i = 0; i <= 360; i+= 360/m) {
      if (m > 0) {
        ellipse(cos(i) * mRad, sin(i) * mRad,dotSize,dotSize);
      }
    }
    ///////////////////////////////////
    var sRad= 90;
    var sColor = map(s,0,59,50,255);
    // var sColor = color(255, 86, 128)
    fill(sColor)
    for (var i = 0; i <= 360; i+= 360/s) {
      if (s > 0) {
        ellipse(cos(i) * sRad, sin(i) * sRad,dotSize,dotSize);
      }
    }
    ///////////////////////////////////
  pop();
}

function displayTime() {
  noStroke();
  fill(255);
  textAlign(CENTER);
  textSize(15);
  // xTime = 60
  // yTime = 40
  xTime = width/2;
  yTime = height/2;
	
	if (h==0) {
		h = 12
	}
  
	//display zero in front of single digit second
  if (s < 10 && m >= 10) {
    text(h + " : " + m + " : 0" + s, xTime, yTime);
	}
	//display zero in front of single digit minute
  else if (s >= 10 && m < 10) {
    text(h + " : 0" + m + " : " + s, xTime, yTime);
	}
	//display zeroes in front of single digit seconds and minutes
  else if (s < 10 && m < 10) {
    text(h + " : 0" +m + " : 0" + s, xTime, yTime);
	}
	//keep seconds and minutes as is when two digits
  else {
    text(h + " : " + m + " : " + s, xTime, yTime);
	}
}

face clock


Now this clock is much more interesting to look at. For this project, I altered another clock I had previously made. In this sketch, I incorporated color, animation (somewhat), and gave this "clock" a lot more personality.

var hr, mn, sc;
var end_hr, end_mn, end_sc;

function setup() {
 createCanvas(400,400); 
}

function draw() {
  background(255);
  
  hr = hour();
  mn = minute();
  sc = second();
  end_hr = map(hr % 12,0,12,0,360);
  end_mn = map(mn, 0, 60, 0, 360);
  end_sc = map(sc, 0, 60, 0, 360);
  
  /////////// time /////////////////////////
  
  //Display time
  if (sc < 10) {
    noStroke();
    fill(135, 158, 163);
    textAlign(CENTER);
    textSize(20);
    strokeWeight(5);
    text(hr + " : " + mn + " : 0" + sc, 80, 30);
  } else {
    noStroke();
    fill(135, 158, 163);
    textAlign(CENTER);
    textSize(20);
    strokeWeight(5);
    text(hr + " : " + mn + " : " + sc, 80, 30);
  }
  
  push();
  strokeWeight(8);
  noFill();
  angleMode(DEGREES);
  translate(width/2,height/2);
  rotate(-90);
  //seconds - innermost
  stroke(164, 206, 216);
  arc(0, 0, 250, 250, 0, end_sc);
	
  //minutes - middle
  stroke(35, 126, 196); 
  arc(0, 0, 320, 320, 0, end_mn);

  //hours - outside
  stroke(31, 56, 119); 
  arc(0,0,345,345,0,end_hr);
  pop();
  
  ///////////// static face ///////////////
  push();
  angleMode(DEGREES);
  translate(width/2,height/2);
  rotate(-90);
  
  //Top of face
  stroke(0);
  strokeWeight(7);
  noFill();
  arc(0,0,280,280,280,80);
  
  //Bottom of face
  noFill();
  arc(0,0,300,300,150,210);
  pop();

  //black eyebrows 
  stroke(0);
  fill(0);
  rectMode(CENTER);
  rect(130, 150, 25, 5, 15);
  rect(270, 150, 25, 5, 15);
  
  //eyes
  ellipseMode(CENTER);
  ellipse(120, 200, 20, 20);
  ellipse(280, 200, 20, 20);
  
  //nose
  noStroke();
  strokeWeight(6);
  fill(204, 95, 95);
  rect(width/2, 230, 15, 30, 20);
  
  //lips
  stroke(0);
  noFill();
  rect(width/2, 280, 60, 20, 20);
  
  //teeth
  line(width/2, 270, width/2, 290);
  line(width/2 - 15, 270, width/2 - 15, 290);
  line(width/2 + 15, 270, width/2 + 15, 290);
  
  ///////// face animations ///////////////
  
  if (sc % 2 == 0) {
    //eyebrows raise
    //cover old eyebrows w white
      stroke(255);
      strokeWeight(8);
      rectMode(CENTER);
      rect(130, 150, 25, 5, 15);
      rect(270, 150, 25, 5, 15);
    //new raised eyebrows
      strokeWeight(5);
      stroke(0);
      rect(130, 140, 25, 5, 15);
      rect(270, 140, 25, 5, 15);
    
    //mouth becomes smaller
    //cover old mouth
      //lips
      strokeWeight(10);
      stroke(255);
      noFill();
      rect(width/2, 280, 60, 20, 20);
      //teeth
      line(width/2, 270, width/2, 290);
      line(width/2 - 15, 270, width/2 - 15, 290);
      line(width/2 + 15, 270, width/2 + 15, 290);
    //new small mouth
      strokeWeight(6);
      stroke(0);
      ellipse(width/2, 280, 20,20);
	}
}

yalbert-clock

For this project, I wanted to capture how time is not necessarily experienced linearly. Often time is is measured by the speed at which moments pass by. When moments are plentiful, they pass by quickly. However, when we only have a few left, we savor them lest they slip away from us. I did my best to express this in a visual way. Making this clock was fairly straightforward as I was able to reuse a particle system from a previous project. However, I'm not thrilled with how the particles clump together oddly when the minute is midway through. I think the clock is most visually pleasing at the beginning and end of the minute. Because my clock is heavily motion based, I chose to use a minute long loop. However, I think this draws away from using the clock for day long timekeeping (the hours are on the left and minutes on the right).

var offset = 25;
var plugOffset = 10;
var cirlceDist = 15;
var miniFill = 170;
var correctnessIndex = 1;
var plugThickness = 15;
var plugTipThickness = 45;
var plugTipHeight = 25;
var miniSize = 450;
 
var particleSystem;
var voiceSystem;
 
var modes = ["off", "listening", "answering"];
var currMode = "off";
 
var speech;
var mic;
 
var scenarios = []
var nullScenario;
var currScenario;
var anotherDayOfSun;
var activate;
var selectAnswers;
var demi;
var instrumental;
var startTime;
 
var instructionsX = 50;
var instructionsY = 50;
 
var barrier = 450
var baselineSec = 0
var resetted = false;
var subjectiveMin = 0
var numActiveParticles = 220;
var r
var g
var b
 
function setup(){
    angleMode(DEGREES);
    createCanvas(700, 700);
    particleSystem = new ParticleSystem();
    particleSystem.reset();
    baselineSec = second();
    subjectiveMin = minute();
 
}
 
function draw(){
    r = map(second()%60 - baselineSec, 0, 60, 0, 255);
    g = map(subjectiveMin, 0, 60, 0, 255);
    b = map(minute(), 0, 24, 0, 255);
 
    print(second(), baselineSec)
    print(second()%60 - baselineSec)
    print("")
 
    background(r, g, b);
    currMode = "listening";
    particleSystem.updateOpacity();
    particleSystem.updateVelocities();
    particleSystem.updatePosition();
    particleSystem.draw();
    // print(resetted)
    if(second()%60 == baselineSec &amp;&amp; resetted == false){
      particleSystem.reset();
      resetted = true;
      subjectiveMin =(subjectiveMin + 1)%60
    }
    if(second() != baselineSec){
      resetted = false;
    }
    drawHours();
    drawMins();
}
 
function drawMins(){
  for(i = 1; i &lt;= 2; i++){
    for(j = 1; j &lt;= 30; j++){ if(i == 1){ minValue = j; }else{ minValue = j + 30; } if(subjectiveMin &gt; minValue){
        opacity = 255;
      }else{
        opacity = 100;
      }
      fill(255-r, 255-g, 255-b, opacity);
      ellipse(width - 20 - 12*2+ 12*i, j*12 + 20, 10, 10);
      //text(minValue, width - 20 - 12*2+ 12*i, (j-1)*12 + 20)
 
    }
  }
}
 
function drawHours(){
  for(i = 0; i &lt; 24; i++){ if(hour() &gt; i){
      opacity = 255;
    }else{
      opacity = 100;
    }
    fill(255-r, 255-g, 255-b, opacity);
    ellipse(20, i*12 + 20, 10, 10);
  }
}
 
//courtesy of Golan Levin (http://cmuems.com/2015c/november-4/)
function ParticleSystem(){
    this.bigParticles = [];
    this.myParticles = [];
    this.nParticles = 300;
    this.particleSize = 10;
    this.isVisible = false;
    this.opacity = 0;
    this.reset = function(){
      this.myParticles = [];
      numActiveParticles = 220
        for (var i = 0; i &lt; this.nParticles; i++) {
            var distFromCenter = random(0, miniSize/2);
            var degree = random(0, 360);
            var rx = cos(degree)*distFromCenter + width/2;
            var ry = sin(degree)*distFromCenter;
            this.myParticles[i] = new Particle(rx, ry, 10, random(.7, 1), true);
        }
 
        for(i = 0; i &lt; 80; i+=2){
          var x1 = width/2 + i*3 + 10;
          var x2 = width/2 - i*3 - 10;
          var y = -i*3 + barrier;
          this.myParticles[i] = new Particle(x1, y, 10, random(.7, 1), false);
          this.myParticles[i+1] = new Particle(x2, y, 10, random(.7, 1), false);
        }
    }
 
    this.setForScenario = function(scenario){
        if(this.bigParticles.length != scenario.possibleAnswers.length){
            for(ansInd = 0; ansInd &lt; scenario.possibleAnswers.length; ansInd++){
                this.addToBigParticles(scenario.answerProbabilities[ansInd]*250);
            }
        }
        for(ind = 0; ind &lt; this.bigParticles.length; ind++){
            if(ind == scenario.selectedInd){
                this.bigParticles[ind].answering = true;
            }else{
                this.bigParticles[ind].answering = false;
            }
        }
    }
 
    this.addToBigParticles = function(goalSize){
        index = floor(random(0, particleSystem.nParticles));
        changingParticle = particleSystem.myParticles[index];
        changingParticle.goalSize = goalSize;
        particleSystem.bigParticles.push(changingParticle);
    }
 
    this.updateVelocities = function(){
        var gravityForcex = 0;
        var gravityForcey = -.17;
 
 
        for (var i = 0; i &lt; this.myParticles.length; i++) {
            var ithParticle = this.myParticles[i];
            var px = ithParticle.px;
            var py = ithParticle.py;
 
 
            ithParticle.addForce(gravityForcex, gravityForcey);
 
            for (var j = 0; j &lt; i; j++) { var jthParticle = this.myParticles[j]; var qx = jthParticle.px; var qy = jthParticle.py; var mutualAttractionAmount = (ithParticle.mass * jthParticle.mass)/2; var dx = px - qx; var dy = py - qy; var dh = sqrt(dx*dx + dy*dy); var componentInX = dx/dh; var componentInY = dy/dh; var proportionToDistanceSquared = 1.0/(dh*dh); var attractionForcex = mutualAttractionAmount * componentInX * proportionToDistanceSquared; var attractionForcey = mutualAttractionAmount * componentInY * proportionToDistanceSquared; if (dh &gt; (ithParticle.mass + jthParticle.mass)/2 * 8) {
                    ithParticle.addForce( attractionForcex,  attractionForcey); // add in forces
                    jthParticle.addForce(-attractionForcex, -attractionForcey); // add in forces
                }else{
                    ithParticle.addForce( -attractionForcex,  -attractionForcey); // add in forces
                    jthParticle.addForce(attractionForcex, attractionForcey);  // add in forces
                }
            }
        }
    }
 
    this.updatePosition = function(){
        for (var i = 0; i &lt; this.myParticles.length; i++) {
                particle = this.myParticles[i];
                particle.update();
        }
    }
 
    this.draw = function(){
        for (var i = 0; i &lt; this.myParticles.length; i++) { particle = this.myParticles[i]; particle.render(this.opacity); } } this.updateOpacity = function(){ if(this.isVisible == false){ //if(this.opacity &gt; 0){
                this.opacity = this.opacity*.9 +0*.1;
            //}
        }else{
            //if(this.opacity &lt; 255){
                this.opacity = this.opacity*.9 + 255*.1 ;               
            //}
        }
 
    }
}
 
 
 
 
//courtesy of Golan Levin (http://cmuems.com/2015c/november-4/)
function Particle(x, y, mass, personalOpacity, canMove){
    this.personalOpacity = personalOpacity;
    this.size = mass;
    this.px= x;
    this.py=y;
    this.vx= 0;
    this.vy=0;
    this.damping = 0.96;
    this.mass = (pow(mass, 3))/100;
    this.bLimitVelocities=true;
    this.bPeriodicBoundaries=false;
    this.bElasticBoundaries=true;
    this.goalSize = mass;
    this.answering = false;
    this.opacity = 0;
    this.movable = canMove;
    this.passedThrough = false;
 
    this.addForce=function(fx,fy){
        var ax=fx/this.mass*1.5;
        var ay=fy/this.mass*1.5;
        if(this.goalSize &lt; 30){ this.vx+=ax; this.vy+=ay; }else{ this.vx+=ax*.1; this.vy+=ay*.1; } } this.update=function(){ this.vx*=this.damping; this.vy*=this.damping; this.limitVelocities(); this.handleBoundaries(); if(this.movable){ this.py-=this.vy; this.px-=this.vx; } // if(abs(this.goalSize-this.size) &gt; 1){
        //     this.size = this.size*.9 + this.goalSize*.1;
        // }
 
        if(this.py &gt; barrier){
          if(this.passedThrough == false){
            numActiveParticles -=1
          }
          this.passedThrough = true
        }
    }
    this.limitVelocities=function(){
        if(this.bLimitVelocities){
            var speed=sqrt(this.vx*this.vx+this.vy*this.vy);
            var maxSpeed=10;
            if(speed&gt;maxSpeed){
                this.vx*=maxSpeed/speed;this.vy*=maxSpeed/speed;
            }
        }
    }
    this.inBounds=function(){
        return(this.px&lt;width&amp;&amp;this.px&gt;0&amp;&amp;this.py&lt;height&amp;&amp;this.py&gt;0);
    }
    this.handleBoundaries=function(){
        if(this.bPeriodicBoundaries){
            if(this.px&gt;width)
                this.px-=width;
            if(this.px&lt;0) this.px+=width; if(this.py&gt;height)
                this.py-=height;
            if(this.py&lt;0) this.py+=height; }else if(this.bElasticBoundaries){ if(particle.py &gt; height){
                this.vy = this.vy*-1; // draw all particles
                this.vx = this.vx*-1;
            }
        }
    }
    this.render=function(parentOpacity){
 
        if(abs(this.goalSize-this.size) &lt; 15 &amp;&amp; this.goalSize &lt; 20){
 
                // this.opacity = 255 -getDist(this.px, this.py, width/2, height/2)*1.2 //+ this.size*this.size;
                // this.opacity = this.opacity*this.personalOpacity 
            noStroke();
 
            if(this.movable){
              if(this.passedThrough == false){
                opacity = 255;
              }else{
                opacity = map(numActiveParticles, 220, 0, 100, 25) //50;
              }
 
              fill(255, 255, 255, opacity);
              ellipse(this.px,this.py,this.size,this.size);
            }
        }else{
            if(this.answering){
                numLayers = 5;
            }else{
                numLayers = 1;
            }
           for(j = 0; j &lt; numLayers; j++){
                diameter = this.size - j*5
                r = lerp(255, 40, 1 - j*.1);
                g = lerp(255, 140, 1 - j*.1);
                b = lerp(255, 250, 1 - j*.1);
 
                fill(r, g, b, 255*(parentOpacity/255));
                ellipse(this.px,this.py,diameter,diameter);
           }
 
        }
    }
}
 
function getDist(x1, y1, x2, y2){
    return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))
}
 
//for testing
 
function mousePressed(){
 
}
 
function keyPressed(){
    if(particleSystem.isVisible){
        particleSystem.isVisible = false;
    }else{
        particleSystem.isVisible = true;
    }
}

breep-clock

Clock:

 

Using The Dot For Every Second In The Day as a launching platform, I wanted to create a clock that helped/reminded the user to optimize their time, through reminding them about the amount they have left. I imagine it to be permanently on the user, and I see it primarily in situ as a digital tattoo which acts as a constant moving reminder (part of me also hates the clunkiness of watches so the unburdened element of a clock tattoo also resonates with me strongly).

While I like the minimalist aesthetic of the clock in terms of its readability, I also feel that a greater graphic quality/style to it would act to help with the element of constantly being reminded as it's quality of being pleasurable to look at would certainly factor into that. I also feel that greater individuality/personally connected tasks would help with a more unique individual experience with the clock.

GIF:

Images:

 

 

Sketches:

 
var prevSec;
var millisRolloverTime;
var loopRunning; 
var button;
var ClockMode = false; 
var AdviceMode = false;
var Width = 800; 
var Height = 300; 
 
var monthAmountTable = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 
 
var minutesIndex = 0; 
var hoursIndex = 0; 
var daysIndex = 0; 
var monthsIndex = 0;
var yearsIndex = 0; 
var decadesIndex = 0; 
var lifetimesIndex = 0; 
 
var minuteActs = ["Stretching\nyour legs",
                  "Telling\nyour parents\nyou love\nthem", 
                  "Messaging\na friend", 
                  "Asking\nthat person\nout",
                  "Brainstorming\nthat idea", 
                  "Taking\nsome time\nfor yourself",
                  "Sketching\na stranger"] 
 
var hourActs = ["Going\n to the\ngym", 
                "Grabbing\nfood with\na friend"]
 
var dayActs = ["Finishing\na piece\nof work", 
               "Getting\nGroceries", 
               "Making a new playlist", 
               "Watching\n a film"]
 
var monthActs = ["Making\na Website", 
                 "Getting\nover that\nbreakup", 
                 "Finding a new hobby"] 
 
var yearActs = ["Learning\n10 songs\non an\ninstrument", 
                "Writing\na book"] 
 
var decadeActs = ["Working\non your\nmental health", 
                  "Forgiving\nyour parents"] 
 
var lifetimeActs = ["Raising\nHell", 
                    "Living a\nfulfilled life"] 
 
var lastChangeSeconds = 0; 
var waitTimeSeconds = 60000; 
 
var lastChangeMinutes = 0;
var waitTimeMinutes = 60; 
 
var lastChangeHours = 0; 
var waitTimeHours = 24; 
 
var lastChangeMonths = 0; 
 
var lastChangeYears = 0; 
var waitTimeYears = 12; 
 
var lastChangeDecade = 0; 
var waitTimeDecades = 10; 
 
//--------------------------
function setup() {
  createCanvas(800, 300);
  background(0); 
  millisRolloverTime = 0;
 
  loopRunning = false; 
  getInput(); 
	var waitTimeMonths = monthAmountTable[month() -1]; 
}
 
//-------------------------
 
function getInput() { 
 
  input = createInput();
  input.position((Width/2) - 125, Height/2);
 
  button = createButton('Your Time Left');
  button.position(input.x + input.width + 20, Height/2);
 
 
  fill(255); 
  textFont("Futura"); 
  textAlign(CENTER);
  textSize(25);
  text("Your Age in this lifetime", Width/2, Height/2 - 50);  
 
 
  button.mousePressed(modeChange); 
}
 
function modeChange(){
  ClockMode = true;}
 
function keyPressed(){ 
  if (ClockMode == true && keyCode == RIGHT_ARROW) {
    ClockMode = false; 
    AdviceMode = true;}
 
  else if (AdviceMode == true && keyCode == LEFT_ARROW){
    AdviceMode = false;
    ClockMode = true;}
}
 
function changeIndex(){ 
  if (minutesIndex < 4){ 
      minutesIndex += 1}
  else if ( minutesIndex > 4){
      minutesIndex = 0;}
 
} 
 
//--------------------------
function draw() {
 
  if (ClockMode == true) { 
 
  button.remove();
  input.remove();
 
 
  background(0);
 
  var monthKeyTable = [0, 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6] 
  var dayOfWeekTable = [6, 7, 0, 1, 2, 3, 4, 5] 
 
 
 
  var weekDay = ((year() % 100) / 4 ) - (((year() % 100) / 4 ) % 1) + day() + monthKeyTable[month()] + 6 + 18
 
  var LifeExpectancy =  72.74 - input.value(); 
 
 
 
  var De = 10 / (year() % 10);  
  var Y = (month() / 12);
  var Mo = (day() / monthAmountTable[month() -1]); 
  var W = (weekDay / 7) % 1 ;
  var D = ((hour()+1) / 24); 
  var H = hour();
  var M = minute();
  var S = second();
 
 
 
  // Reckon the current millisecond, 
  // particularly if the second has rolled over.
  // Note that this is more correct than using millis()%1000;
  if (prevSec != S) {
    millisRolloverTime = millis();
  }
  prevSec = S;
  var mils = floor(millis() - millisRolloverTime);
 
  noStroke();
  textAlign(CENTER);
  textSize(15); 
  fill(255); ///////////////////////////////////
  text("seconds left", (56.25 + 25), 65); 
  text("in this minute", (56.25 + 25), 85);   
  text( 60 - second(), (56.25 + 25), 45); 
 
 
  text("minutes left", (56.25 + 25) * 2 + 25, 65); 
  text("in this hour", (56.25 + 25) * 2 + 25, 85); 
  text( 60 - minute(), (56.25 + 25) * 2 + 25, 45); 
 
 
  text("hours left", (56.25 + 25) * 3 + 50, 65); 
  text("in this day", (56.25 + 25) * 3 + 50, 85); 
  text(24 - hour() - 1 , (56.25 + 25) * 3 + 50, 45); 
 
  text("days left", (56.25 + 25) * 4 + 75, 65); 
  text("in this month", (56.25 + 25) * 4 + 75, 85);
  text((monthAmountTable[month() -1] - day()) + 1, (56.25 + 25) * 4 + 75, 45); 
 
 
  text("months left", (56.25 + 25) * 5 + 100, 65);
  text("in this year", (56.25 + 25) * 5 + 100, 85); 
  text((12 - month())+ 1, (56.25 + 25) * 5 + 100, 45); 
 
  text("years left", (56.25 + 25) * 6 + 125, 65); 
  text("in this decade", (56.25 + 25) * 6 + 125, 85); 
  text((10 / (year() % 10)), (56.25 + 25) * 6 + 125, 45); 
 
 
  text("years left\n" + "on average", (56.25 + 25) * 7 + 150, 65); 
  text(round(72.74 - input.value()) - 1, (56.25 + 25) * 7 + 150, 45); 
 
  text("press right key to get some suggestions to fill this time", Width/2, Height - 15); 
 
 
  var lifeExpectancyBarWidth = map(LifeExpectancy, 72.74, 0, 0, 160); 
 
  var decadeBarWidth = map(De, 10, 0, 0, 160); 
 
  var yearBarWidth = map(Y, 1/12, 1, 0, 160); 
 
  var monthBarWidth = map(Mo, 0, 1, 0, 160); 
 
  var dayBarWidth = map(D, (1/24), 1, 0, 160); 
 
  var hourBarWidth   = map(H, 0, 23, 0, 160);
 
  var minuteBarWidth = map(M, 0, 59, 0, 160);
 
  var secondBarWidth = map(S, 0, 59, 0, 160);
 
  // Make a bar which *smoothly* interpolates across 1 minute.
  // We calculate a version that goes from 0...60, 
  // but with a fractional remainder:
  var secondsWithFraction = S + (mils / 1000.0);
  var secondsWithNoFraction = S;
  var secondBarWidthChunky = map(secondsWithNoFraction, 0, 60, 0, width);
  var secondBarWidthSmooth = map(secondsWithFraction,   0, 60, 0, 160);
 
  fill(150); 
  rect((56.25 * 3) + (50 * 2), 100, 50, 160);      //h
  rect((56.25 * 2) + 50, 100, 50, 160);   //m
  rect(56.25, 100, 50,  160); //s
 
 
  rect((56.25 * 4) + (50 * 3), 100, 50, 160); 
  rect((56.25 * 5) + (50 * 4), 100, 50, 160); 
  rect( (56.25 * 6) + (50 * 5), 100, 50, 160); 
 
  rect((56.25 * 7) + (50 * 6), 100, 50, 160);     
 
 
  fill(170, 1, 20);
  rect((56.25 * 3) + (50 * 2), 100, 50, 160 - hourBarWidth);      //h
  rect((56.25 * 2) + 50, 100, 50, 160 - minuteBarWidth);   //m
  rect(56.25, 100, 50,  160 - secondBarWidthSmooth); //s
 
 
  rect((56.25 * 4) + (50 * 3), 100, 50, 160 - monthBarWidth); 
  rect((56.25 * 5) + (50 * 4), 100, 50, 160 - yearBarWidth); 
  rect( (56.25 * 6) + (50 * 5), 100, 50, 160 - decadeBarWidth); 
 
  rect((56.25 * 7) + (50 * 6), 100, 50, 160 - lifeExpectancyBarWidth); 
 
 
  }
 
  else if ( AdviceMode == true){
 
 
 
  var nowSeconds = millis() 
  var elapsedSeconds = nowSeconds - lastChangeSeconds; 
 
  var nowMinutes = minute(); 
  var elapsedMinutes = nowMinutes - lastChangeMinutes; 
 
  var nowHours = hour();
  var elapsedHours = nowHours - lastChangeHours; 
 
  var nowMonths = month();
  var elapsedMonths = nowMonths - lastChangeMonths; 
 
  var nowYears = year(); 
  var elapsedYears = nowYears - lastChangeYears; 
 
  var nowDecade = year() % 10;
  var elapsedDecades = nowDecade - lastChangeDecade; 
 
 
  if (elapsedSeconds > waitTimeSeconds){
    lastChangeSeconds = nowSeconds; 
    minutesIndex = (minutesIndex + 1) % minuteActs.length;}
 
  if (elapsedMinutes > waitTimeMinutes){
    lastChangeMinutes = nowMinutes; 
    hoursIndex = (hoursIndex + 1) % hourActs.length;}
 
  if (elapsedHours > waitTimeHours){
    lastChangeMinutes = nowMinutes; 
    hoursIndex = (hoursIndex + 1) % hourActs.length;}  
 
 
  fill(0); 
  rect(0, 0, 800, 800); 
 
  noStroke();
  textAlign(CENTER);
  textSize(15); 
  fill(255); 
 
 
  text(minuteActs[minutesIndex], (56.25 + 25), Height * (2/5)); 
  text("in this minute", (56.25 + 25), Height -65);   
  //text( 60 - second(), (56.25 + 25), 45); 
 
 
  text(hourActs[hoursIndex], (56.25 + 25) * 2 + 25, Height * (2/5)); 
  text("in this hour", (56.25 + 25) * 2 + 25, Height - 65); 
  //text( 60 - minute(), (56.25 + 25) * 2 + 25, 45); 
 
 
  text(dayActs[daysIndex], (56.25 + 25) * 3 + 50, Height * (2/5));
  text("in this day", (56.25 + 25) * 3 + 50, Height -65); 
  //text(24 - hour() - 1 , (56.25 + 25) * 3 + 50, 45); 
 
  text("try", (56.25 + 25) * 4 + 75, 45); 
 
 
  text(monthActs[monthsIndex], (56.25 + 25) * 4 + 75, Height * (2/5)); 
  text("in this month", (56.25 + 25) * 4 + 75, Height - 65);
  //text((monthAmountTable[month() -1] - day()) + 1, (56.25 + 25) * 4 + 75, 45); 
 
 
  text(yearActs[yearsIndex], (56.25 + 25) * 5 + 100, Height * (2/5)); 
  text("in this year", (56.25 + 25) * 5 + 100, Height - 65); 
  //text((12 - month())+ 1, (56.25 + 25) * 5 + 100, 45); 
 
  text(decadeActs[decadesIndex], (56.25 + 25) * 6 + 125, Height * (2/5));
  text("in this decade", (56.25 + 25) * 6 + 125, Height - 65); 
  //text(10 / (year() % 10), (56.25 + 25) * 6 + 125, 45); 
 
 
  text(lifetimeActs[lifetimesIndex], (56.25 + 25) * 7 + 150, Height * (2/5)); 
  text("in this lifetime", (56.25 + 25) * 7 + 150, Height - 65); 
  //text(round(72.74 - input.value()) - 1, (56.25 + 25) * 7 + 150, 45);   
 
  text("press left key to look at your time", Width/2, Height - 15);  
  } 
}

 

 

nixel-clock

7:10AM

11:30PM

12:01AM

I had a tough time with this project, not because of a lack of ideas, but because of an excess. I'd brainstormed a ton of ideas, all of them relating to the concept of time, but not necessarily to clocks. Below is a snapshot of all the things I was pondering.

My problem was that I didn't know how exactly to relate these ideas to clocks, and how to represent them in an interesting visual way. I honestly think if I'd just focused on one and did some more research it would have turned out fine.

I was still stuck between ideas half way through the week when I thought of hourglasses. Hourglasses are a very visual object that help to keep time, so I started brainstorming for that.

I wanted to create one hourglass to cover the span of one day with day draining into night, then flipping it at sundown and having night drain into day. I was even going to extract the realtime sunrise and sunsets on weather websites to make it more accurate, however this was too difficult to implement in a short amount of time.

The underlying concept behind the hourglass was to represent how much time we have left rather than how much time has passed like a regular clock.  So once again, due to my awareness of the extent of my coding skills and the amount of time (haha) I had left to finish this, I decided to simplify my concept. It ended up being 3 glasses...an hourglass, a minuteglass, and a secondglass. There are a lot of things I want to fix about this...like making the 'sand' more lively, lining up the drop of the ball with the rise of the sand at the bottom, doing an actual flipping animation, somehow coding gravity for the sand, and making everything just flow smoother. My code is also clumsy and could be much more refined and efficient.

However, I think finished is better than perfect, and what I ended up with is an accumulation of many mistakes I made in the process, and I think this needed to happen so that I could learn from it and get it out of the way.

//thank you golan for the template
var millisRolloverTime;
var prevSec;
 
function setup() {
  createCanvas(750, 400);
  rectMode(CORNERS);
  noStroke();
  }
 
function draw() {
  background(200);
  var H = hour();
  var M = minute();
  var S = second();
  if (prevSec != S) {
    millisRolloverTime = millis();
  }
  prevSec = S;
  var mils = (floor(millis() - millisRolloverTime))/1000.0;
  var secmils = S + mils;
  var mins = M+(map(secmils, 0, 59, 0, 1));
  var hours = (H%12)+(map(mins, 0, 59, 0, 1));
 
  //hourglass
  fill(19, 70, 70);
  rect(0, 0, 250, height/2);
  rect(0, height/2 , 250, height);
 
  //minuteglass
  fill(19, 86, 86);
  rect(250, 0, 500, height/2);
  rect(250, height/2 , 500, height);
 
  //secondglass
  fill(52, 119, 106);
  rect(500, 0, width, height/2);
  rect(500, height/2 , width, height);
 
  hrglassBottom();
  hrglassTop();
  minglassBottom();
  minglassTop();
  secglassBottom();
  secglassTop();
 
  secBall(mils);
  minBall(secmils);
  hrBall(mins);
 
  fill(255);
 
  //hr mask
  triangle(250, 0,  145, height/2 , 250, height/2 );
  triangle(0, 0,  110, height/2 , 0, height/2 );
  triangle(0, height/2,  110, height/2 , 0, height);
  triangle(145, height/2,  250, height , 250, height/2);
 
  //min mask
  triangle(250, 0,  360, height/2 , 250, height/2 );
  triangle(250, height/2,  360, height/2 , 250, height );
  triangle(500, 0,  390, height/2 , 500, height/2);
  triangle(390, height/2,  500, height , 500, height/2);
 
  //sec mask
  triangle(500, 0,  610, height/2 , 500, height/2 );
  triangle(500, height/2,  610, height/2 , 500, height );
  triangle(width, 0,  645, height/2 , width, height/2);
  triangle(645, height/2,  width, height , width, height/2);
}
 
 
function minBall(mils){
  var y = map(mils, 0, 1, height/2, 435);
  var x = width/2;
  ellipse(x, y, 30, 30);
}
 
function secBall(mils){
  var x = 625;
  var y = map(mils, 0, 1, height/2, 435);
  ellipse(x, y, 30, 30);
}
 
function hrBall(mils){
    var r = map(hour(), 0, 60, 0, 255);
    fill(r, 0, 100);
    var x = 125;
    var y = map(mils, 0, 1, height/2, 435);
    ellipse(x, y, 30, 30);
}
 
//hr
function hrglassTop(){
  var r = map(hour(), 0, 24, 110, 190);
  fill(r, 9, 9);
  let glassHeight = map(hour(), 0, 24, 0, height/2);
 
  rect(0, glassHeight, 250, height/2);
}
 
function hrglassBottom(){
  let glassHeight = map(hour(), 0, 24, height, height/2);
  beginShape();
  var r = map(hour(), 0, 24, 110, 190);
  fill(r, 9, 9);
  vertex(0, height);
  for (var i = 0; i &lt;= 250; i++){
    vertex(i, glassHeight);
  }
  vertex(250, height);
  endShape();
}
 
//minute
function minglassTop(){
  let glassHeight = map(minute(), 0, 60, 0, height/2);
  var r = map(minute(), 0, 60, 255, 100);
  fill(r, 0, 0);
  rect(250, glassHeight, 500, height/2);
}
 
function minglassBottom(){
let glassHeight = map(minute(), 0, 60, height, height/2);
  beginShape();
  var r = map(minute(), 0, 60, 255, 100);
  fill(r, 0, 0);
  vertex(250, height);
  for (var i = 250; i &lt;= 500; i++){
    vertex(i, glassHeight);
  }
  vertex(500, height);
  endShape();
}
 
//second
function secglassTop(){
  let glassHeight = map(second(), 0, 60, 0, height/2);
  var g = map(second(), 0, 60, 150, 100);
  fill(255, g, g);
    rect(500, glassHeight, width, height/2);
}
 
function secglassBottom(){
  let glassHeight = map(second(), 0, 60, height, height/2+20);
  beginShape();
  var g = map(second(), 0, 60, 150, 100);
  fill(255, g, g);
  vertex(500, height);
  for (var i = 500; i &lt;= width; i++){
    vertex(i, glassHeight);
  }
  vertex(width, height);
  endShape();
}

sapeck-Clock

With no human present:

When a human is present, the time runs away from the human (either via face detection or mouse click):

The time running away to the other side of the screen:

Embeded demo (responds to both mouse clicks and face detection in the browser):

This clock is scared of people. You can't run away from time if it runs away from you. I imagine this clock on someone's nightstand or in their kitchen like a pet fish. Like a fish swims to the opposite side of the bowl when a hand nears, the time runs to the opposite side of the screen when anyone is in view. The clock is both infuriating, as it doesn't tell you the time when you need it and reflective how necessary time is. I don't think I am as experienced enough to make the time look truly animated and living. I added a flicker and blinks to make it seem more alive, but the motion from an easing function isn't natural enough.

/* Sapeck    9/20/2017
/* Sapeck    9/20/2017
"sapeck-Clock"
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
 
var DEBUG = false;
 
var prevSec;
var millisRolloverTime;
var mils;
var moveStartTime = 0;
var sideCounter = 0;
var backColor = 255;
var returning = false;
 
var moveTime = [0, 0, 0];
var sideMoveTime = 0;
var currSideToX = 0;
var moving = false;
var sideMoving = false;
 
var ctracker;
 
function setup() {
  createCanvas(800, 800);
  millisRolloverTime = 0;
 
  var videoInput = createCapture();
  videoInput.size(640, 480);
  //videoInput.position(0, 0);
 
  ctracker = new clm.tracker();
  ctracker.init();
  ctracker.start(videoInput.elt);
}
function draw() {
  time = [hour(), minute(), second(),0];
  updateMils(time[2]);
  time[3] = mils;
  showTime = [nf(time[0],2), nf(time[1],2), nf(time[2],2), nf(time[0],3)];
  stutterDelay = false;
 
 
  if (moving) backColor--;
  else backColor++;
  if (backColor > 255) backColor = 255;
  else if (backColor < 0) backColor = 0;
  background(backColor);
 
  var positions = ctracker.getCurrentPosition();
  noFill();
  stroke(color(0,255,0));
  if (positions.length > 0 && DEBUG) {
    rect(map(positions[0][0], 0, 640, 0, width), map(positions[0][1], 0, 480, 0, height), 100, 100);
  }
 
  if (positions.length > 0 || mouseIsPressed) {
    moving = true;
    sideCounter++;
    if (!sideMoving) moveStartTime = millis();
  } else {
    moving = false;
  }
 
  push();
  translate(width/2, height/2);
  y = [
    int(height/2 * function_PennerEaseOutElastic(moveTime[0])),
    int(height/2 * function_PennerEaseOutElastic(moveTime[1])),
    int(height/2 * function_PennerEaseOutElastic(moveTime[2]))
  ];    
  showTime[1] = nf(int(time[1]+(30*function_PennerEaseOutElastic(moveTime[0])*noise(moveTime[0]))),2);
  showTime[0] = nf(int(time[0]+(30*function_PennerEaseOutElastic(moveTime[0]+0.0025)*noise(moveTime[0]+0.0025))),2);
  showTime[2] = nf(int(time[2]+(30*function_PennerEaseOutElastic(moveTime[0]+0.0025)*noise(moveTime[0]+0.0025))),2);
  if (!sideMoving) {
    if (moving) {
      moveTime[0] += 0.005;
      if (moveTime[0] >= 0.020) moveTime[1] += 0.005;
      if (moveTime[1] >= 0.040) moveTime[2] += 0.005;
      for (var i=0;i<moveTime.length;i++) if (moveTime[i] > 1) moveTime[i] = 1;
    } else if (!moving && (moveTime[0] > 0 || moveTime[1] > 0 || moveTime[2] > 0)) {
      moveTime[0] -= 0.0025;
      if (moveTime[0] <= 0.980) moveTime[1] -= 0.0025;
      if (moveTime[1] <= 0.960) moveTime[2] -= 0.0025;
      for (var j=0;j<moveTime.length;j++) if (moveTime[j] < 0) moveTime[j] = 0;
    } else {
      for (var k=0;k<moveTime.length;k++) moveTime[k] = 0;
 
      if (time[3] % 22 == 0) {
        var jitterRand = int(random(0,3));
        var change = int(random(-1,2));
        showTime[jitterRand] = nf(time[jitterRand] + change, 2);
        stutterDelay = true;
      }
    }
  }
  textFont('VT323');
  textSize(100);
  fill(255 - backColor);
  if (stutterDelay) fill((255 - backColor) + random(80, 100));
  noStroke();
  textAlign(CENTER, CENTER);
 
  var xShift = 0;
  if (moveTime[0] > 0.40) {
    showTime[1] = "00";
    var blink = (""+frameCount).substr(-2, 1);
    var blinkB = (""+frameCount).substr(-3, 1);
    if (4 < blink && blink < 7 && (blinkB == 4 || blinkB == 9)) showTime[1] = "++";
  }
  if (moveTime[0] == 1 && moving) {
    if (millis() - moveStartTime >= 5000 || sideCounter > 200) {
      if (!sideMoving) {
        if (!mouseIsPressed) currSideToX = width - int(map(positions[0][0], 0, 640, 0, width));
        else currSideToX = mouseX;
        console.log(currSideToX, width, mouseX);
      }
      sideMoving = true;
 
      xShift = int((width/2 - currSideToX) * function_PennerEaseOutElastic(sideMoveTime));
 
      sideMoveTime += 0.0025;
      if (sideMoveTime > 1) sideMoveTime = 1;
    }
  } else if (!moving && sideMoving) {
    xShift = int((width/2 - currSideToX) * function_PennerEaseOutElastic(sideMoveTime));
 
    sideMoveTime -= 0.0025;
    if (sideMoveTime < 0) sideMoving = false;
  }
 
  push();
  translate(xShift, y[0]);
  text(showTime[1], 0, 0);
  pop();
 
  if ((moveTime[0] <= 0.470 && moving) || (moveTime[0] <= 0.2 && !moving)) {
    push();
    translate(0, y[1]);
    text(":", -50, 0);
    pop();
 
    push();
    translate(0, y[1]);
    text(":", 50, 0);
    pop();
 
    push();
    translate(0, y[2]);
    text(showTime[0], -100, 0);
    pop();
 
    push();
    translate(0, y[2]);
    text(showTime[2], 100, 0);
    pop();
  }
 
  pop();
 
  //if (stutterDelay) delay(500);
}
 
function updateMils(S) {
  if (prevSec != S) {
    millisRolloverTime = millis();
  }
  prevSec = S;
  mils = floor(millis() - millisRolloverTime);
}
 
// From https://github.com/golanlevin/Pattern_Master converted from Java
function function_PennerEaseOutElastic(t) {
  if (t==0) return 0.0; 
  if (t==1) return 1.0;
  var  p = 0.3;
  var  s = p/4;
 
  return (pow(2, -10*t) * sin( (t-s)*(2*PI)/p ) + 1);
}

chromsan-clock

Prevent time from passing by knocking away the incoming seconds. The more you prevent time from passing, the faster the seconds will come. If one of the seconds makes it past you, time is reset and can even go into the future.

(use side to side arrow keys to control the paddle)

I liked the idea of making some sort of a game for this project, as time is usually quite a large part of games. I also wanted to make a clock that was not quite accurate, so that you could have some control over the clock's speed. I took inspiration from Pong, so that the player can prevent time from being added to the clock. To give a bit of a challenge, I made time speed up as the player is more successful. This way, if they miss, time is both reset and a couple seconds may be added to the clock. The main issue with using p5.js for this project is that the animation stops drawing when you leave a tab, so the time that is drawn will be different from the real time, and the scoring system gets messed up. I'd like to find a way around this.

(update on 9/25- I've found a kinda hacky way around this to fix the score and time, embedded sketch has been updated)

The green theme denotes AM and red denotes PM.

Original ideas:

Code also on GitHub.

// real time (not based on game)
let realMS, realS, realM, realH; 
// game time (based on game performance)
let gameS, gameM, gameH; 
// previous logged times 
let p_realS, p_realM, p_realH; 
// how often the times appear [0-999]
const timeFreqInit = 999;
let timeFreq = timeFreqInit, timeFreqInc = 20;
// assorted global vars 
const deflectorSpeed = 15, timeSpeed = -10;
const dispTimeY = 80;
 
let deflector, time = 0;
let times = [], score = 1, dispScore = 0, highScore = 0;
let font, fSize = 60, fillCol, backCol;
let millisRolloverTime = 0; 
 
function preload() {
  font = loadFont('digital-7.ttf');
}
 
function setup() {
  createCanvas(600, 750, P2D);
  textFont(font);
  textSize(fSize);
  updateRealTime();
  // to start, game time is the same as real time
  gameS = realS;
  gameM = realM;
  gameH = realH;
  // if it's AM, color green, otherwise red 
  setAmPmCol();
  // paddle 
  deflector = new Deflector(10, 100, width/2, height/4);
}
 
function draw(){
  setAmPmCol();
  fill(fillCol);
  textSize(fSize);
  background(backCol);
  updateRealTime();
  drawGameTime();
  // every time theres a new second...
  if (p_realS != realS){
    millisRolloverTime = millis();
    p_realS = realS;
  }
  realMS = floor(millis() - millisRolloverTime);
  // add a new time based off freq
  if (realMS % timeFreq == 0) {
    time++;
    let expanded = secondsToMin(time);
    let temp = {s: expanded.s, m: expanded.m, h: realH, disp: expanded.s};
    times.push(new Time(temp, random(30, width - 30), height));
  }
 
  for (let i in times) {
    if (times[i].offscreen()){
      // remove offscreen times
      times.splice(i, 1);
    }
    if (times[i].intersects(deflector)){
      // remove times after hitting paddle
      times[i].bounceMove(random(-10,10), random(6, 12));
      if (score &gt; highScore) { highScore = score }
    } 
    if (times[i].escaped() &amp;&amp; !times[i].t.used){
 
      // if the time made it past the paddle
      times[i].t.used = true;
 
      if (-score &lt;= 0){ let res = addToTime(gameS, gameM, gameH, times[i].t.s, times[i].t.m); gameS = res.s; gameM = res.m; gameH = res.h; } // measure the diff between real and game time to get score let d1 = new Date(2018, 9, 20, gameH, gameM, gameS); let d2 = new Date(2018, 9, 20, realH, realM, realS); let d = d2.getTime() - d1.getTime() if (realS - gameS &gt; 0) {score = d /1000;}
      else {score = realS - gameS}
      time = 0;
      timeFreq = timeFreqInit;
    }
    if (times[i].goingUp) {
      // move the times up by speed
      times[i].move(timeSpeed);
    }
    times[i].update();
    times[i].draw();
  }
  deflector.update();
  deflector.draw();
  drawScore();
}
 
function keyReleased() { 
  if (keyIsDown(RIGHT_ARROW)) { deflector.move(deflectorSpeed) }
  else if (keyIsDown(LEFT_ARROW)) { deflector.move(-deflectorSpeed) }
  else { deflector.move(0) }
}
 
function keyPressed() {
  if (keyCode == LEFT_ARROW){ deflector.move(-deflectorSpeed)} 
  if (keyCode == RIGHT_ARROW){ deflector.move(deflectorSpeed)} 
}
 
function updateRealTime() {
  realS = second();
  realM = minute();
  realH = hour() % 12;
}
 
function drawGameTime() {
  textAlign(CENTER);
  text(gameH, width/4, dispTimeY);
  text(":", width/8 * 3, dispTimeY)
  text(gameM, width/4 * 2, dispTimeY);
  text(":", width/8 * 5, dispTimeY)
  text(gameS, width/4 * 3, dispTimeY);
}
 
function drawScore() {
  textSize(25);
  textAlign(CENTER);
  let res = secondsToMin(score);
  let disp, pos = "";
  if (score &lt; 0) {pos = "+"} // check if we need to display minutes if (res.m &gt; 0) {disp = pos + (-1 * res.m) + ":" + res.s}
  else {disp = pos + (-1 * res.s)}
  text(disp, width - 80, 80);
  textSize(12);
  //text("s", width - 150, height- 20);
  textSize(25);
  text("Max:  " + highScore, width - 75, height - 20);
  textSize(12);
  text("s", width - 30, height- 20);
}
 
function secondsToMin(sec) {
  let secRl = sec % 60;
  let minRl = Math.floor(sec / 60);
  return {s: secRl, m: minRl};
}
 
function addToTime(pS, pM, pH, s, m) {\
  // add seconds and minutes new seconds and minutes
  let fixedS = pS + s, fixedM = pM + m, fixedH = pH;
  // case check for if any go over 60 
  if (fixedS &gt;= 60) { 
    let res = secondsToMin(fixedS);
    fixedS = res.s;
    fixedM += res.m;
  }
  if (fixedM &gt;= 60){
    // we can use the same function for mins + hrs
    let res = secondsToMin(fixedM);
    fixedM = res.s;
    fixedH += res.m;
  }
  if (fixedH &gt; 12){
    // kinda hacky but really unlikely to happen
    fixedH = hour() % 12;
  }
  return {h: fixedH, m: fixedM, s: fixedS}
}
 
function setAmPmCol() {
  if (hour() &gt; 12) {fillCol = color(205, 0, 0); backCol = color(20, 0, 0)}
  else { fillCol = color(0, 205, 0); backCol = color(0, 20, 0) }
}
 
// the 'paddle' that used to hit the numbers
class Deflector {
  constructor(h_, w_, x_, y_){
    this.height = h_;
    this.width = w_;
    this.x = x_;
    this.y = y_;
    this.deltaX = 0;
  }
  update() {
    this.x += this.deltaX;
    this.x = constrain(this.x, this.width/2, width - this.width/2);
  }
  move(steps) { this.deltaX = steps }
 
  draw() {
    textAlign(CENTER);
    textSize(70);
    text("___", this.x, this.y);
    textSize(fSize); 
  }
}
 
// the numbers that appear
class Time {
  constructor(t_, x_, y_) {
    this.t = t_;
    this.x = x_;
    this.y = y_;
    this.deltaY = 0;
    this.deltaX = 0;
    this.goingUp = true;
    this.col = color(fillCol.levels[0], fillCol.levels[1], fillCol.levels[2]);
    this.used = false;
  }
  update() {
    this.y += this.deltaY;
    this.x += this.deltaX;
  }
  move(steps) { 
     this.deltaY = steps;
  }
  bounceMove(stepX, stepY){
    this.deltaX = stepX;
    this.deltaY = stepY;
  }
  escaped(){
    if (this.y &lt; height/4) { return true }
    else {return false}
  }
 
  intersects(deflector) { 
    // from https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
    if (deflector.x &lt; this.x + 50 &amp;&amp; deflector.x + deflector.width &gt; this.x + 40 &amp;&amp;
        deflector.y &lt; this.y + 10 &amp;&amp; deflector.y + deflector.height &gt; this.y - 40) {
      if (this.goingUp) {
        // if the time hits the deflector...
        score++; 
        if (score &gt; 0 &amp;&amp; timeFreq &gt;= 750){
          timeFreq -= timeFreqInc;
        }
 
      }
      this.goingUp = false;
      this.t.disp = '#'
      return true;
    }
    return false;
  }
 
  offscreen() {
    if (this.y &lt; -40 || this.y &gt; height + 40) return true;
    else return false;
  }
 
  draw() {
    textAlign(CENTER);
    if (this.escaped()){
      let a = this.col.levels[3];
      this.col.setAlpha(a - 15);
      fill(this.col);
      text(this.t.disp, this.x, this.y);
    } else {
      fill(fillCol);
      text(this.t.disp, this.x, this.y);
 
    }
 
  }
}

weirdie-Clock

The original idea for this piece was something that represented growth and decay in terms of nature. This evolved into a clock that drew generative artwork - one that changed throughout the day and grew more complex the longer you looked at it. For this, I started off with the code from The Coding Train's Perlin Noise Flow Field as a base template of sorts. The seed for the Perlin noise field is generated based on the day and year. Every second there is a white particle added, every minute a blue, and every red an hour, each traveling at different speeds to show how time "flies by". One can tell how many minutes or hours they have been staring at the clock, either watching or wasting time, by how many particles there are.

To continue this project, there are two things I would like to expand upon. First, there is currently a maximum number of each type of particle, as having an unlimited number results in a continuously lower framerate, and I would like to find a way to remove this limitation. Additionally, I would want to see this displayed so that it is continuously generating - that is, it would show how many seconds, minutes, and hours had passed in the day thus far.

12:04-12:05, with very little time elapsed:

3:13-3:14, with a around 60 minutes passed:

8:32-8:33, with way too many hours passed:

 

Sketches:

Code (it's really ugly I know):

var prevSec;
var millisRolloverTime;
 
var inc = 0.1;
var scl = 20;
var cols, rows;
var numpart = 0;
 
var zoff = 0;
var radius = 250;
var particles = [];
var flowfield;
 
function setup() {
  createCanvas(700, 700);
  background(40);
  cols = floor(width/scl);
  rows = floor(height/scl);
  noiseSeed(day*year);
  millisRolloverTime = 0;
 
  //seconds particles
  for(var i = 0; i &lt; 60; i++)
  {
    var angle = 3*PI/2 + (TWO_PI/60*i);
    particles[i] = new Particle(radius*cos(angle)+width/2, radius*sin(angle)+height/2);
  }
 
  //minute particles
  for(var i = 60; i &lt; 120; i++)
  {
    var angle = 3*PI/2 + (TWO_PI/60*(i-60));
    particles[i] = new Particle(radius*cos(angle)+width/2, radius*sin(angle)+height/2);
    particles[i].type = 1;
  }
 
  //hour particles
  for(var i = 120; i &lt; 132; i++)
  {
    var angle = 3*PI/2 + (TWO_PI/12*(i-120));
    particles[i] = new Particle(radius*cos(angle)+width/2, radius*sin(angle)+height/2);
    particles[i].type = 2;
  }
 
 
  flowfield = new Array(cols*rows);
}
 
function draw() {
  //draw the circle of circles
  for(var i = 0; i &lt; 12; i++)
  {
    var angle = 3*PI/2 + (TWO_PI/12*i);
    noFill();
    strokeWeight(1);
    stroke(255, 50);
    ellipse(radius*cos(angle)+width/2, radius*sin(angle)+height/2, 30, 30);
    strokeWeight(0.05);
  }
 
  background(0,3);
 
  strokeWeight(5);
  stroke(255);
  var angle = 3*PI/2 + (TWO_PI/60*second());
 
  var nextsec = abs((second()+1)%60);
  var angle = 3*PI/2 + (TWO_PI/60*nextsec);
  particles[second()].active = true;
  particles[nextsec] = new Particle(radius*cos(angle)+width/2, radius*sin(angle)+height/2);
  particles[second()].maxspeed = 5;
 
  var nextmin = abs((minute()+1)%60);
  var angle = 3*PI/2 + (TWO_PI/60*nextmin);
  particles[60+minute()].active = true;
  particles[nextmin+60] = new Particle(radius*cos(angle)+width/2, radius*sin(angle)+height/2);
  particles[60+minute()].type = 1;
  particles[60+minute()].maxspeed = 3;
 
  var nexthour = abs((hour()+1)%60);
  var angle = 3*PI/2 + (TWO_PI/12*nexthour);
  var h = hour()%12;
  particles[120+h].active = true;
  particles[120+h].type = 2;
  particles[120+h].maxspeed = 1.5;
 
 
 
  var yoff = 0;
  for (var y = 0; y &lt; rows; y++)
  {
    var xoff = 0;
    for (var x = 0; x &lt; cols; x++)
    {
      var index = (x+y*cols);
      var angle = noise(xoff, yoff, zoff)*TWO_PI*4;
      var v = p5.Vector.fromAngle(angle);
      v.setMag(1);
      flowfield[index] = v;
      xoff += inc;
    }
    yoff += inc;
    zoff += 0.0005;
  }
for (var i = 0; i &lt; particles.length; i++) {
    if (particles[i].active) {
      particles[i].follow(flowfield);
      particles[i].update();
      particles[i].show();
      particles[i].edges();
    }
  }
strokeWeight(10);
  stroke(86, 255, 238);
  var angle = 3 * PI / 2 + (TWO_PI / 60 * (minute()));
  point(radius * cos(angle) + width / 2, radius * sin(angle) + height / 2);
  strokeWeight(5);
}
 
function Particle(startx, starty) {
  this.active = false;
  this.pos = createVector(startx, starty);
  this.vel = createVector(0, 0);
  this.acc = createVector(0, 0);
  this.maxspeed = 2;
  this.type = 0;
 
  this.h = 0;
 
  this.prevPos = this.pos.copy();
 
  this.update = function() {
    this.vel.add(this.acc);
    this.vel.limit(this.maxspeed);
    this.pos.add(this.vel);
    this.acc.mult(0);
  }
 
this.follow = function(vectors) {
    var x = floor(this.pos.x / scl);
    var y = floor(this.pos.y / scl);
    var index = x + y * cols;
    var force = vectors[index];
    this.applyForce(force);
  }
 
  this.applyForce = function(force) {
    this.acc.add(force);
  }
 
  this.show = function() {
 
    if (this.active) {
      if (this.type == 0) {
        strokeWeight(5);
        stroke(255);
        var angle = 3 * PI / 2 + (TWO_PI / 60 * (second()));
        point(radius * cos(angle) + width / 2, radius * sin(angle) + height / 2);
        strokeWeight(1);
      } else if (this.type == 2) {
        strokeWeight(20);
        stroke(255, 111, 86);
        var angle = 3 * PI / 2 + (TWO_PI / 12 * (hour()));
        point(radius * cos(angle) + width / 2, radius * sin(angle) + height / 2);
        strokeWeight(15);
      } else if (this.type == 1) {
        strokeWeight(10);
        stroke(86, 255, 238);
        var angle = 3 * PI / 2 + (TWO_PI / 60 * (minute()));
        point(radius * cos(angle) + width / 2, radius * sin(angle) + height / 2);
        strokeWeight(5);
      }
 
      line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
      this.updatePrev();
    }
  }
 
  this.updatePrev = function() {
    this.prevPos.x = this.pos.x;
    this.prevPos.y = this.pos.y;
  }
 
  this.edges = function() {
 
    if (this.pos.x &gt; width) {
      this.pos.x = 0;
      this.updatePrev();
    }
    if (this.pos.x &lt; 0) { this.pos.x = width; this.updatePrev(); } if (this.pos.y &gt; height) {
      this.pos.y = 0;
      this.updatePrev();
    }
    if (this.pos.y &lt; 0) {
      this.pos.y = height;
      this.updatePrev();
    }
  }
}

airsun-clock

When the next minute arrives, return to the top screen where hour, minute, weekday, and date will be displayed
Hour and minute are also displayed on the top left of the screen
The battery on the top right will decrease as time goes

First sketch on illustrator

For this project, I was inspired by one of my most used action, swiping messages on my phone. Because I interacted with it a lot, not only the time displayed on the top centre of the screen reminds me the time, the time marked on each messages, and the changes of the remaining battery all indicates the pass of time. Therefore, I wanted to create a representation of my interaction with time. In the work, the hand swiping the messages represents second. When a new minute comes, the screen will go to the starting mode with hour, minute, date, and weekday on it. Moreover, the abstract feed at the background emphasize my continuous interaction with my phone (walking while swiping). This time, I reflected on the problem of how my drawing may not go well with the vector drawing in p5js,. Therefore, I first implemented my drawing (demonstration shown below), and then changed to vector drawing for consistency.

experimenting with drawing and movements
// Clair Sijing Sun
// Clock Project
// 60-212
// Sep 20, 2018
 
var prevSec;
var millisRolloverTime;
var frames = [];
var secondH ;
var counter = 0;
var weekdayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", 
  "Thursday", "Friday", "Saturday"]
var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var listofApps = ['WEIBO', 'WECHAT', 'GROUPME', 'GMAIL', 'LINKEDIN', 'FACEBOOK', 'STUDENT', 'SOUNDCLOUD'];
var appL ;
var randomN ;
var batteryR ;
var batteryG ;
var batteryB ;
var batteryL = 25;
var backrockX = 50;
var backrockY = 0;
var barH = 72;
var handM1 = 383;
var handM2 = 369;
var finger = [];
var skin = [];
var feetH ;
var feetH2 ;
 
 
 
//--------------------------
function setup() {
  createCanvas(600, 600);
  millisRolloverTime = 0;
  feetH = height;
  feetH2 = height + 100;
 
}
 
//--------------------------
function preload(){
  frames.push(loadImage("https://i.imgur.com/6LcHHng.png"));
  //frames.push(loadImage("https://i.imgur.com/od1uGbs.png"));
  frames.push(loadImage("https://i.imgur.com/gHs88Af.png"));
  finger.push(loadImage("https://i.imgur.com/QfwFtyL.png"));
  finger.push(loadImage("https://i.imgur.com/WFPnTt3.png"));
  skin.push(loadImage("https://i.imgur.com/vXlzYE7.png"));
  skin.push(loadImage("https://i.imgur.com/KFbFtYv.png"));
}
 
//--------------------------
function draw() {
  background(144, 173, 189); 
 
  push();
  fill(0, 10);
  if (backrockY &lt; height || backrockY == height){
    backrockY = backrockY + 1;
  }else{backrockY = 0}
  for (i = 0; i &lt; 20; i++){ ellipse(backrockX * i, backrockY+i*10, 4, 120); } pop(); appL = listofApps.length; push(); fill(232,158,78); rect(190,40,210,408, 20); pop(); // Fetch the current time var H = hour(); var Min = minute(); var S = second(); var D = day(); var M = month(); var week = new Date().getDay(); // Reckon the current millisecond, // particularly if the second has rolled over. // Note that this is more correct than using millis()%1000; if (prevSec != S) { millisRolloverTime = millis(); } prevSec = S; var mils = floor(millis() - millisRolloverTime); noStroke(); fill('black'); var currTimeString = "Time: " + (H%12) + ":" + nf(M,2) + ":" + nf(S,2) + ((H&gt;12) ? "pm":"am");
 
 
  var hourBarWidth   = map(H, 0, 23, 0, width);
  var minuteBarWidth = map(Min, 0, 59, 0, width);
  var secondBarWidth = map(S, 0, 59, 0, width);
  var secondsWithFraction = S + (mils / 1000.0);
  var secondsWithNoFraction = S;
  var secondBarHeightChunky = map(secondsWithNoFraction, 0, 60, 0, width);
 
  //for displaying the moving hand
  if (mils &lt; 500){
    counter = 0;
  }else{
    counter = 1;
  }
 
  //draw the feet
  push();
  fill(0);
  strokeWeight(4);
  stroke(0);
  if (mils &lt; 500){
    feetH = map(mils, 0, 500, height+100, height);
    feetH2= map(mils, 0, 500, height, height+100);
  } else {
    feetH = map(mils, 500, 1000, height, height+100);
    feetH2 = map(mils, 500, 1000, height+100, height);
  }
  ellipse(width/4, feetH, 140, 200);
  ellipse(width/4+300, feetH2, 140, 200);
  fill(255, 100);
  arc(width/4, feetH-50, 100, 90, PI, 2*PI, CHORD);
  pop();
 
  //draw the top bar
  push();
  fill(255, 100);
  rect(185, 45, 220, 25, 20);
  pop();
 
  //controlling the movement of seconds
  var secondBarHeightSmooth = height;
  if (mils &lt; 300) { secondBarHeightSmooth = map(mils, 0, 300, 420, 228); }else if (mils &gt;= 300 &amp;&amp; mils &lt; 700){
    secondBarHeightSmooth = 228;
  }else{secondBarHeightSmooth = map(mils, 700, 1000, 228, 39);
  }
 
    //changing background for seconds
    push();
    textSize(20);
    fill(255, 150);
    if ((''+S).length == 1){
        S = '0'+ S;
    }
    rect(width/3, secondBarHeightSmooth-25, 190, 40, 10);
    fill(232,158,7);
    text(S, 350, secondBarHeightSmooth);  
    textSize(12);
    //if (S){
        //randomN = random(S%8);
    //}
    text(listofApps[int(S%8)], 220, secondBarHeightSmooth-12);
    fill(0)
    text('Notification', 220, secondBarHeightSmooth+5);
 
    pop();
 
 
    fill(255);
    barH = map(S, 0, 60, 72, 392);
    rect(393, barH, 2, 20, 5);
 
    //display of hour and minutes at the beginning 
    if (S &lt; 1){
        if (mils &lt; 700){
            secondH = 126;
        }else { secondH = map (mils, 700, 1000, 126, -65);}
    }else{
        secondH = -10;
    }
 
    push();
    textStyle(NORMAL);
    textSize(40);
    fill(255);
    textFont('Helvetica');
    if ((''+Min).length == 1){
        Min = '0'+ Min;
    }
    text(H + ":" + Min, width/2.5, secondH);
    textSize(12);
    text(weekdayNames[week]+","+monthNames[M-1]+ " " + D, 224, secondH+(145-126));
 
    pop();
 
    //display of mins and hours on top left
    push();
    fill(255);
    text(H+ ":" + Min, 201, 62);
    pop();
 
    //home bar
    fill(255);
    rect(240, height-170, 100, 5, 10);
 
 
 
  //image(frames[1], 80, -20, 500, 700);
  //image(frames[0], 80, -20, 500, 700);
 
  push();
  noFill();
  stroke(0);
  strokeWeight(9);
  rect(185, 42, 218, 405, 25);
  beginShape();
  strokeWeight(1);
  fill(0);
  curveVertex(245, 47);
  curveVertex(245, 47);
  curveVertex(261, 61);
  curveVertex(329, 61);
  curveVertex(345, 47);
  curveVertex(345, 47);
  endShape();
  pop();
  image(skin[counter],100, -18, 430, 655);
  image(finger[counter], 200, 220, 300, 300);
  //image(finger[counter], 200, 220, 300, 300);
 
  push();
  noFill();
  beginShape();
  stroke(0);
  strokeWeight(4);
  print(mouseX, mouseY);
  curveVertex(180, 245);
  curveVertex(180, 245);
  curveVertex(159, 256);
  curveVertex(152, 270);
  curveVertex(161, 278);
  curveVertex(180, 281);
  curveVertex(180, 281);
  endShape();
 
  beginShape();
  curveVertex(180, 299);
  curveVertex(180, 299);
  curveVertex(161, 308);
  curveVertex(155, 322);
  curveVertex(160, 333);
  curveVertex(180, 334);
  curveVertex(180, 334);
  endShape();
 
  beginShape();
  curveVertex(180, 365);
  curveVertex(180, 365);
  curveVertex(165, 374);
  curveVertex(157, 388);
  curveVertex(164, 398);
  curveVertex(180, 398);
  curveVertex(180, 398);
  endShape();
 
  beginShape();
  curveVertex(408, 243);
  curveVertex(408, 243);
  curveVertex(426, 272);
  curveVertex(435, 292);
  curveVertex(446, 309);
  curveVertex(457, 322);
  curveVertex(457, 322);
  curveVertex(474, 348);
  curveVertex(480, 365);
  curveVertex(482, 390);
  curveVertex(482, 410);
  curveVertex(482, 432);
  curveVertex(482, 450);
  curveVertex(488, 495);
  curveVertex(496, 526);
  curveVertex(501, 545);
  curveVertex(505, 562);
  curveVertex(518, 605);
  curveVertex(518, 605);
  endShape();
  if (counter == 1 ){
    handM1 = 383;
    handM2 = 360;
 
  }else{
    handM1 = 383;
    handM2 = 369;
 
  }
 
  beginShape();
  curveVertex(433, 326);
  curveVertex(433, 326);
  curveVertex(407, 340);
  curveVertex(393, 354);
  curveVertex(handM1, handM2);
  curveVertex(handM1, handM2);
  endShape();
 
  beginShape();
  curveVertex(285, 453);
  curveVertex(285, 453);
  curveVertex(286, 461);
  curveVertex(296, 469);
  curveVertex(308, 466);
  curveVertex(300, 476);
  curveVertex(301, 490);
  curveVertex(309, 501);
  curveVertex(318, 504);
  curveVertex(307, 508);
  curveVertex(309, 528);
  curveVertex(315, 544);
  curveVertex(332, 570);
  curveVertex(359, 600);
  curveVertex(359, 600);
  //curveVertex(handM1, handM2);
  endShape();
 
 
 
  pop();
 
  //battery drawing
  if (Min &lt; 40){
    batteryR = 255;
    batteryG = 255;
    batteryB = 255;
  } else {
    batteryR = 213;
    batteryG = 73;
    batteryB = 61;
  }
 
  batteryL = (60-Min)/60 * 25;
  push();
  fill(batteryR,batteryG,batteryB);
  rect(width/2+57, 53, batteryL, 12, 4);
  noFill();
  stroke(255);
  rect(width/2+57, 53, 25, 12, 3);
 
 
 
  pop();
 
 
  push();
  fill(144, 173, 189);
  rect(width/4,0, 400, 37);
  pop();
 
 
 
}

The GIF:

chaine-clock

My actual clock:

When I was working on sketching ideas for this assignment last Friday during class, I struggled quite a bit. I think I had too many ideas that were too different. I thought of incorporating trees and seasons, planets and its rotations, but I found myself constantly at a block that I couldn't get past. Throughout the week I pondered about time and I think I put too much pressure on time being a grandiose thing that needed a counterpart grandiose object to represent it. I took myself away from that thought and reflected upon my time spent living in a new building for the fall semester. My kitchen sink had had a leak in it and my parents and I had to put a container under it for the first few days to prevent it from spilling out everywhere. After it was filled, we'd empty it and the cycle began again. I decided to incorporate that as my clock to represent time in my own trivial, personal way.

Clock at 1:39 AM to 1:40 AM:

Clock at 10:02 PM:

Clock at 11:59 AM to 12 PM (you can see a small light green square forming on the lower middle with each new hour):

function setup(){
// Simple p5.js Clock Template
// Golan Levin, 2016
 
var prevSec;
var prevMin;
var prevHour;
var millisRolloverTime;
var secRolloverTime;
var hourRolloverTime;
var cubeList;
var x = [];
var squareSize;
 
//--------------------------
function setup() {
  createCanvas(400, 650);
  millisRolloverTime = 0;
  secRolloverTime = 0;
  hourRolloverTime = 0;
  cubeList = [];
  squareSize = 15;
  for (var k = 0; k < 24; k++){
    randomX = int(random(35, width - squareSize - 20));
    randomY = int(random(200, height - squareSize - 20));
    append(x, randomX);
    append(x, randomY);
    append(x, int(random(0,230)));
    append(x, int(random(0,230)));
    append(x, int(random(0,230)));
    append(x, int(random(1, 9)));
    append(cubeList, x);
    x = [];
  }
  print(cubeList);
}
//--------------------------
 
//--------------------------
function draw() {
  background(255,255,255,150); // My favorite pink
 
  // Fetch the current time
  var H = hour();
  var M = minute();
  var S = second();
 
  // Reckon the current millisecond, 
  // particularly if the second has rolled over.
  // Note that this is more correct than using millis()%1000;
  if (prevSec != S) {
    millisRolloverTime = millis();
  }
  prevSec = S;
 
  if (prevMin != M) {
    secRolloverTime = millis();
  }
  prevMin = M;
 
  if (prevHour != H) {
    hourRolloverTime = millis();
  }
  prevHour = H;
 
  var smoothMin = floor(millis() - secRolloverTime);
  var mils = floor(millis() - millisRolloverTime);
  var smoothHour = floor(millis() - hourRolloverTime);
 
  //var leftMinDiv = map(height, 0, 800, 
 
 
  //fill(128,100,100);
  //text("Hour: "   + H, 10, 22);
  //text("Minute: " + M, 10, 42);
  //text("Second: " + S, 10, 62);
  //text("Millis: " + mils, 10, 82);
  //text("SmoothHour: " + smoothHour, 10, 102);
 
  var hourBarWidth   = map(H, 0, 23, 0, width);
  var minuteBarWidth = map(M, 0, 59, 0, width);
  var secondBarWidth = map(S, 0, 59, 0, width);
 
  // Make a bar which *smoothly* interpolates across 1 minute.
  // We calculate a version that goes from 0...60, 
  // but with a fractional remainder:
  var secondsWithFraction   = S + (mils / 1000.0);
  var secondsWithNoFraction = S;
  var secondBarWidthChunky  = map(secondsWithNoFraction, 0, 60, 0, width);
  var secondBarWidthSmooth  = map(secondsWithFraction,   0, 60, 0, width);
  var smoothMinFraction = M + secondsWithFraction;
  var smoothMinBar = map(smoothMinFraction, 0, (M*60) + 60, 0, width);
 
  //////////
 
  //noStroke();
  //fill(40);
  //rect(0, 100, hourBarWidth, 50);
  //fill(80);
  //rect(0, 150, minuteBarWidth, 50);
  //fill(120);
  //rect(0, 200, secondBarWidthChunky, 50);
  //fill(160);
  //rect(0, 250, secondBarWidthSmooth, 50);
  //fill(200);
  //rect(0, 50, smoothMinBar, 50);
  noStroke();
  var circleSize = 20;
 
  if (mils >= 300){
    var mapping2 = map(mils, 300, 999, 15, (height - (M * 10) - 10));
    fill(255, 153, 153);
    ellipse(width/2, mapping2, circleSize, circleSize);
  }
 
  var hourMap = map(smoothHour, 0, 3600000, height, 190);
  var minMap = map(smoothMin, 0, 60000, 10, 0);
  var minAdj = map(M, 0, 59, height - 15, 180);
 
  beginShape();
  for (var i = 0; i <= width+1; i++) {
    var mapWidth = map(i, i, width, PI, 2*PI); 
    var x = float(i);
    var mapping = map(mils, 0, 500, -PI, 0);
    var bounce = map(mils, 0,999, 9, 0);
    var y = 10 * sin(bounce * mapWidth * 0.1 * mapping) + (height - (M * 10) - 10);
    if (x >= 0 && x <= width+1){
      vertex(x, y);
    }
  }
 
 
  mapTankColR = map(M, 0, 60, 204, 255);
  mapTankColG = map(M, 0, 60, 255, 200);
  mapTankColB = map(M, 0, 60, 255, 200);
 
  fill(mapTankColR, mapTankColG, mapTankColB, 150);
  vertex(width, height);
  vertex(0, height);
  endShape();
 
  var minCount = 5;
 
  //255,200,200
  for (var j = height - 45; j > 50; j -= 50) {
    push();
    fill(128, 100, 100);
    text(minCount, 15, j);
    minCount += 5;
    pop();
  }
 
  for (var j = height - 10; j > 50; j -= 10) {
    push();
    stroke(0,0,0);
    strokeWeight(1);
    line(0, j, 10, j);
    pop();  
  }
 
  if (M == 59 && S == 59) {
    if (H == 23) {
      cubeAppear(0, mils);
    }
    else{
      cubeAppear(H+1, mils);
    }
  }
  for (var hor = 0; hor < H; hor++){
    push();
    var mapRotate = map(mils, 0, 999, 0, 2*PI);
    noFill();
    stroke(cubeList[hor][2],cubeList[hor][3],cubeList[hor][4]);
    rect(cubeList[hor][0] + (squareSize*cos(mapRotate * cubeList[hor][5]))/4, cubeList[hor][1] + (squareSize*sin(mapRotate * cubeList[hor][5]))/4,squareSize,squareSize);
    pop();
  }
  //0 0 153
}
 
function cubeAppear(hour, mils){
  if (hour == 0){
    setup();
    return;
  }
  else{
    noFill();
    strokeWeight(1);
    mapOpp = map(mils, 0, 800, 0, 255);
    stroke(cubeList[hour - 1][2],cubeList[hour - 1][3],cubeList[hour - 1][4], mapOpp);
    rect(cubeList[hour - 1][0],cubeList[hour - 1][1],squareSize,squareSize);
  //for (var cube = 0; cube < cubeList.length; cube++){
  //  push();
  //  noFill();
  //  stroke(cubeList[cube][2],cubeList[cube][3],cubeList[cube][4]);
  //  rect(cubeList[cube][0],cubeList[cube][1],squareSize,squareSize);
  //  pop();
  //}
  }
}