shuann-clock

I had a lot of trouble coming up with ideas, but I really liked one of the ancient time keeping tool that only tracked time to the hours. In addition I also wanted to crate a clock that can blends into the everyday routine that you shouldn't need to pay much attention to.  I was then inspired by "rainy mood (https://rainymood.com/)" which I listen to while working as the rain sound can keep me calm and concentrated. Thus I decided to make this clock that is all about that. It is designed so that you don't really need to pay much attention to the visuals. For every hour that passed by, there will be a thunder sound to remind you that it's now the next hour.

I am overall satisfied with the final product. I originally imagined this to be a full scale projection that blends into a wall to create the illusion of a rainy day. However, I had to scale it down due to 1). time constraints and 2). the style of computer graphics might not be the best to create that illusion(?).

Sketch:

var rain = [];
var offset = 30;
var s;
var m;
var h;
var preH=-1;
var sizeY = 10;
var sizeO = 9;
 
 
function preload() {
    rainSound = loadSound("rain.ogg");
    thunder = loadSound("thunder.ogg");
}
 
function setup() {
  createCanvas(500,500); 
  frameRate(30);
  rainSound.loop();
}
 
function draw() {
  drawBackground();
  s = second();
  m = minute();
  h = hour();
 
  if (h != preH){
    thunder.play();
    preH=h;
  }
 
  if (frameCount % 10 == 0){
    createNewDrop();
  }
 
  push();
  for (var elem=0; elem < rain.length; elem++){
    rain[elem].move();
    if (rain[elem].bound() && elem != rain.length-1){
      rain.splice(elem,1);
    }
    rain[elem].render();
  }
  pop();
 
  drawWall();
  drawCandle();
}
 
function drawCandle(){
  //plate
  push();
  translate(width*2/3-20, height*2/3-20);
  fill("lightpink");
  noStroke();
  rect(-80,0,160,7);
  ellipse(0,7,160,20);
  fill("pink");
  ellipse(0,0,160,20);
  pop();
 
  push();
  translate(width*2/3-20, height*2/3-20);
 
  noStroke();
  fill("offWhite");
  if(h < 12){// candle length mapped to miuntes && burn for 12h each
    //candle1
    var c1 = map(h*60+m, 0, 720, -60, -5);
    ellipse(-30,c1-3,50,10);
    rect(-55,c1-3,50,-c1);
    ellipse(-30,-3,50,10);//stationary
    stroke(0);
    strokeWeight(2);
    line(-30,c1-3,-30,c1-7);
    drawFire(-30,c1-7);
 
    //candle2
    noStroke();
    ellipse(25,-58,50,10);
    rect(0,-58,50,60);
    ellipse(25,2,50,10);//stationary
    stroke(0);
    strokeWeight(2);
    line(25,-58,25,-62);
 
 
  } else {
    ellipse(-30,-8,50,10);
    rect(-55,-8,50,5);
    ellipse(-30,-3,50,10);//stationary
    stroke(100);
    strokeWeight(2);
    line(-30,-8,-30,-12);
 
    var c2 = map(h%12*60+m, 0, 720, -60, -5);
    noStroke();
    ellipse(25,c2+2,50,10);
    rect(0,c2+2,50,-c2);
    ellipse(25,2,50,10);//stationary
    stroke(0);
    strokeWeight(2);
    line(25,c2+2,25,c2-2);
    drawFire(25,c2-2);
  }
  pop();
}
 
function drawFire(x,y){
  push();
  translate(x,y);
  noStroke();
  fill(225,243,94,100);
  if (s%2 == 0){
    sizeY += 0.5;
    sizeO += 0.1;
  } else{
    sizeY -= 0.5;
    sizeO -= 0.1;
  }
  ellipse(0,-4,8,sizeY);
  fill(231,122,19,200);
  ellipse(0,-3,7,sizeO);
  fill(241,60,47,240);
  ellipse(0,-2,4,7);
 
  pop();
}
 
function drawBackground(){
  background(150);
  var r0 = 0;
  var g0 = 76;
  var b0 = 153;
  var r1 = 70;
  var g1 = 130;
  var b1 = 180;
  for (var i=0; i < 30; i++){
    noStroke();
    var r = map(i,0,30,r0,r1);
    var g = map(i,0,30,g0,g1);
    var b = map(i,0,30,b0,b1);
    fill(r,g,b);
    rect(0,i*10,width/2+offset*2-5,10);
  }
}
 
function drawWall(){
  push();
  fill(	251, 241, 224);
  noStroke();
  rect(width/2+offset*2,0,width/2+30,height);
  rect(0,height*2/3-38,width,height/2);
 
  push();
  // fill(245,232,202);
  fill(220,210,180);
  translate(width/2+offset*2,0);
  quad(0,0,20,0,20,299,0,290);
  pop();
 
  push();
  fill(255,250,250);
  translate(0,height*2/3-45);
  quad(0,0,width/2+75,0,width/2+80,10,0,10);
  pop();
 
  pop();
  drawFrame();
}
 
function drawFrame(){
  push();
  fill(92,53,33);
  noStroke();
  quad(width/2+offset*2-5,0,width/2+offset*2+15,0,
      width/2+offset*2+15,height*2/3-45,width/2+offset*2-5,height*2/3-60);//right
  fill(97,62,38);
  quad(0,height/2+23,width/2+offset*2-5,height/2+23,
      width/2+offset*2+16,height/2+39,0,height/2+39);//bottom
  pop();
 
  drawStand();
  drawFlower();
  drawBucket();
}
 
function drawBucket(){
  push();
  translate(50,height*0.8);
  strokeWeight(5);
  stroke(80);
  noFill();
  ellipse(0,0,160,20);
 
  push();
  strokeWeight(10);
  stroke(161,122,99);
  strokeJoin(ROUND);
  beginShape();
  curveVertex(60,-60);
  curveVertex(60,-60);
  curveVertex(70,-90);
  curveVertex(78,-100);
  curveVertex(90,-103);
  curveVertex(100,-100);
  curveVertex(104,-94);
  curveVertex(105,-90);
  curveVertex(105,-85);
  curveVertex(103,-85);
  endShape();
  //umbrella
  noStroke();
  scale(1.5);
  translate(-25,0);
  fill(119,191,225);
  triangle(40,-50,70,-40,0,200);
  fill(107,172,229);
  triangle(45,-50,75,-40,0,200);
  fill(115,185,247);
  triangle(50,-50,80,-40,0,200);
  fill(117,199,252);
  triangle(60,-48,80,-42,0,200);
  fill(115,185,247);
  triangle(70,-44,90,-35,0,200);
  pop();
 
  line(80,0,70,100);
  line(80,0,70,5);
  line(70,5,60,8);
  line(60,8,52,100);
  line(60,8,50,9);
  line(50,9,40,9.5);
  line(40,10,35,100);
  line(40,9.5,20,9.5);
  line(20,10,18,100);
  line(20,9.5,10,9.5);
  line(0,10,0,100);
  line(-20,10,-18,100);
  line(-40,9,-35,100);
  pop();
}
 
function drawStand(){
  push();
  translate(width/3-20,height/2+offset*2);
  noStroke();
  fill(216,200,225);
  quad(20,0,380,0,400,30,0,30);
  fill(216,191,216);
  rect(0,30,400,15);
  fill(201,186,209);
  rect(10,45,380,250);
 
  //drawer1
  fill(220,204,209); 
  quad(50,60,430,60,420,70,55,70);
  quad(55,130,430,130,430,135,50,135);
  fill(242,224,230);
  quad(50,60,55,70,55,130,50,135);
 
  //drawer2
  fill(220,204,209);
  quad(50,160,430,160,420,170,55,170);
  fill(242,224,230);
  quad(50,160,55,170,55,230,50,240);
  pop();
}
 
function drawFlower(){
  push();
  //draw stem
  translate(width/2+170,height/3+25);
	stroke(52,131,34);
	strokeWeight(4);
	line(-20,-100,55,128);
	line(5,-30,10,-50);
	line(10,-50,50,-90);
	line(10,-50,12,-90);
  line(23,30,60,-40);
	line(10,-9,-70,-60);
	line(-33,-35,-60,-20);
	line(-20,-100,-50,-120);
	line(-20,-100,-20,-130);
 
	//draw buds 
	noStroke();
	fill(220,182,225);
	star(10,-50, 10, 20,7);
	star(50,-90, 13, 25,7);
	star(12,-90, 13, 25,7);
	star(60,-40, 13, 25,7);
	star(-70,-60, 13, 25,7);
	star(-33,-35, 10, 20,7);
	star(-50,-120, 10, 20,7);
	star(-25,-80, 13, 25,7);
	star(-15,-115, 13, 25,7);
	star(0,-15, 13, 25,7);
	star(-60,-20, 10, 20,7);
 
	fill("offwhite");
	ellipse(10,-50,7);
	ellipse(50,-90,7);
	ellipse(12,-90,7);
	ellipse(60,-40,7);
	ellipse(-70,-60,7);
	ellipse(-33,-35,7);
	ellipse(-50,-120,7);
	ellipse(-25,-80,7);
	ellipse(-15,-115,7);
	ellipse(0,-15,7);
	ellipse(-60,-20,7);
	pop();
 
	//draw vessel
	push();
	fill(198,228,255,200);
	noStroke();
	rect(width/2+170,height/3+25,60,130);
	ellipse(width/2+200,height/3+155,60,10);
	pop();
}
 
function createNewDrop(){
  for (var i = 0; i < 10; i++){
    var newDrop = new rainDrop(int(random(-20,width/2+offset*2)), int(random(-20,height/3)));
    rain.push(newDrop);
  }
}
 
function rainDrop(x, y){
  this.x = x;
  this.y = y;
  this.s = 1;
  this.pos = [[this.x, this.y]];
  this.velX = int(random(1,3));
  this.velY = 2;
 
  this.render = function(){
    stroke(204,229,255);
    if (this.pos.length == 1) {
      ellipse(this.x, this.y, this.s, this.s);
    } else {
      for (var i=1; i<this.pos.length; i++){
        strokeWeight(this.s);
        line(this.pos[i-1][0], this.pos[i-1][1], this.pos[i][0], this.pos[i][1]);
      }
    }
  }
 
  this.move = function() {
    this.x += this.velX;
    this.y += this.velY;
    this.pos.push([this.x, this.y]);
 
    if (random() < 0.8){ this.velX = int(random(2)); } else { this.velX = int(random(-2,3)); } this.checkLength(); } pop this.checkLength = function() { if (this.pos.length > 15){
      this.pos.shift(0);
    }
  }
 
  this.bound = function() {
    if (this.pos[0][0] > width/2+offset*2 || this.pos[0][1] > height*2/3-38){
      return true;
    } else {
      return false;
    }
  }
}
 
//taken from:https://p5js.org/examples/form-star.html
function star(x, y, radius1, radius2, npoints) {
  var angle = TWO_PI / npoints;
  var halfAngle = angle/2.0;
  beginShape();
  for (var a = 0; a < TWO_PI; a += angle) {
    var sx = x + cos(a) * radius2;
    var sy = y + sin(a) * radius2;
    vertex(sx, sy);
    sx = x + cos(a+halfAngle) * radius1;
    sy = y + sin(a+halfAngle) * radius1;
    vertex(sx, sy);
  }
  endShape(CLOSE);
}