Project 6: Abstract Clock

(The illustration file wasn’t loading properly so I had to embed it twice!)

Since Nintendo recently announced that Hyrule Warriors: Age of Calamity is coming out soon, I decided to create a clock inspired by The Legend of Zelda’s Breath of the Wild. The sky changes color depending on the hour, the clouds move across the sky every minute, and pink sparkles appear every second.

breath of the wild
var dusk;
var dawn;
var sparkleX = [];
var sparkleY = [];
var randomW = [];
var randomH = [];
let yPerl = 0.0;

function preload() {
    mySon = loadImage("link_illustration.png");
}

function setup() {
    createCanvas(480, 300);
    //angleMode(DEGREES);

    greenDusk = color(162, 219, 202); //dusk sky color
    yellowDawn = color(252, 246, 211); //dawn sky color
    mountainColor = color(56, 116, 150); //color of the mountains
    cloudColor = color(225, 223, 184); //colod of the clouds
    ledgeColor = color(19, 68, 97); //color of Link's ledge
    ledgeShadow = color(4, 42, 50, 75); //color of ledge shadow
    hyrulePink = color(255, 145, 203); //color of the sparkles

    lerpValue = 0;
    dusk = "nightfall";
    dawn = "daybreak";
    sunlight = "sunrise";
    moonlight = "twilight";

    //sparkles
    for (i = 0; i < 60; i++) {
        sparkleX[i] = random(width);
        sparkleY[i] = random(175, 300);
        randomW[i] = random(3, 6);
        randomH[i] = random(3, 6);
    }
}

function draw() {
    background(0);
    noStroke();
    sky(); //sky incremently changes color based on hour

    push(); //clouds move across sky based on minute
    var m = minute();
    driftingCloud = map(m, 0, 60, 0, width);
    translate(driftingCloud, 0);
    clouds();
    pop();

    mountains(); //randomly generated mountains
    castle(); //castle in the distance

    //sparkles in the horizon
    fill(hyrulePink);

    for (i = 0; i < second(); i++) {
        rect(sparkleX[i], sparkleY[i], randomW[i], randomH[i]);
    }
    
    //ledge that Link stands on
    ledge();

    //illustration of Link
    scale(0.2);
    image(mySon, 1100, 350);

}

//sky incremently changes color each hour
function sky() {
    var h = hour();

    if (dawn === "daybreak") {
        lerpValue = map(h, 23, 0, 0, 1);
    }
    else {
        lerpValue = map(h, 0, 23, 0, 1);
    }

    if (h < 12) {
        lerpValue = map(h, 0, 11.5, 0, 1);
    } else {
        lerpValue = map(h, 11.5, 23, 1, 0);
    }
    
    var skyChange = lerpColor(greenDusk, yellowDawn, lerpValue);
    fill(skyChange);
    rect(0, 0, width, height);
}

//mountain horizon
function mountains() {
    fill(mountainColor);
    beginShape();
    let xPerl = 0;

    for (let x = 0; x <= width; x += 10){
        let y = map(noise(xPerl), 0, 1, 150, 200);
        vertex(x, y);
        xPerl += 0.2;
    }

    yPerl += 0.2;
    vertex(width, height);
    vertex(0, height);
    endShape(CLOSE);
}

//clouds based on minute
function clouds() {
    fill(cloudColor);
    var m = minute();

    for (var c = 0; c <= m; c++) {

        //top left middle cloud
        push();
        scale(0.75);
        translate(0, -50);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //middle cloud
        push();
        translate(150, -20);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //top left small cloud
        push();
        scale(0.5);
        translate(-70, -80);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //bottom left large cloud
        push();
        scale(1.25);
        translate(-90, -20);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //top right cloud
        push();
        scale(0.75);
        translate(320, -80);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //top middle cloud
        push();
        scale(0.5);
        translate(50, -110);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();

        //far left middle cloud
        push();
        translate(-250, -50);
        beginShape();
        curveVertex(0, 150);
        curveVertex(10, 140);
        curveVertex(25, 130);
        curveVertex(45, 135);
        curveVertex(70, 115);
        curveVertex(100, 120);
        curveVertex(140, 100);
        curveVertex(190, 140);
        curveVertex(210, 150);
        endShape(CLOSE);
        pop();
    }
}

//ledge where Link is standing
function ledge() {
    push();
    fill(ledgeColor);
    translate(width/1.8, height + 10);
    beginShape();
    vertex(-30, -50);
    vertex(0, -90);
    vertex(90, -85);
    vertex(130, -40);
    vertex(160, 50);
    vertex(-60, 50);
    endShape(CLOSE);
    pop();

    push();
    fill(ledgeShadow);
    translate(width/1.8, height + 10);
    beginShape();
    vertex(-10, -75);
    vertex(0, -90);
    vertex(90, -85);
    vertex(130, -40);
    vertex(160, 50);
    endShape(CLOSE);
    pop();
}

//castle in the horizon
function castle() {
    fill(mountainColor);
    rect(125, 110, 30, 100); //castle tower
    rect(102, 150, 75, 100); //castle building
    rect(90, 165, 100, 50); //castle ledge
    rect(122.5, 125, 35, 10); //lower level of castle
    triangle(120, 110, 140, 50, 160, 110); //main spire
    triangle(100, 150, 107.5, 110, 115, 150); //left spire
    triangle(165, 150, 172.5, 110, 180, 150); //right spire
    triangle(85, 200, 92.5, 130, 100, 200); //bottom left spire
    triangle(180, 200, 187.5, 130, 195, 200); //bottom right spire

    //windows
    fill(greenDusk);
    rect(135, 110, 5, 10);
    rect(130, 110, 2, 10);
    rect(135, 140, 10, 10);

    //jagged rocks from mountain
    push();
    fill(mountainColor);
    rectMode(CENTER);
    translate(450, 225);
    rotate(PI/1.2);
    rect(0, 0, 50, 250);
    rotate(PI/4.0);
    rect(415, -150, 40, 250);
    rect(200, -50, 35, 250);
    pop();
}
Sketch of the clock’s features.
Quick sketch of Link I drew for this project.

Leave a Reply