Angela Lee – Final Project

Instructions: Please expand your browser window as much as possible since my canvas is at the width of 600! Thank you 🙂
To interact with my speculative comic panel, here are a couple of interactions you can try.
To speed up the subway car, press the “f” key.
To slow down the subway car, press the “s” key. (Note: you cannot make the subway go backwards. If you press this key too many times, it will reset to its original speed.)
To reset the subway car speed, press the “r” key.
In frames 1 & 2, click your mouse around to see some falling stars.

sketch

/*
 * Angela Lee
 * Section E
 * ahl2@andrew.cmu.edu
 * Final Project
 */

// FRAME 1 VARIABLES
var f1height = 270; // height of first frame
var f1width = 275; // width of first frame
var f1x = 22.5; // upper left x-pos of first frame
var f1y = 12.5; // upper left y-pos of first frame
var f1spacing = 9; // spacing to the right of the first frame
var accelerate = 0; // how much the subway car speeds up/slows down
var skyBlue; // top of the sky color
var skyYellow; // bottom of the sky color
var waterYellow; // top of the water color
var waterBlue; // bottom of the water color
var shootingStarArray = []; // array for shooting stars
var ripples = []; // array for the ripples

// FRAME 2 VARIABLES
var f2width = 270; // width of second frame
var f2height = 130; // height of second frame
var f2spacing = 11.5; // spacing below the second frame
var planetx = 400; // x position of the big planet
var subwayStarArray = []; // array for subway stars


function setup(){
	createCanvas (600, 300);
    background(27, 34, 45);

    // gradient for the sky in frame 1
    skyBlue = color(2, 76, 98); // top of the sky color
    skyYellow = color(233, 255, 191); // bottom of the sky color

    // gradient for the water in frame 1
    waterYellow = color(252, 239, 194); // top of the water color
    waterBlue = color(59, 98, 115); // bottom of the water color

    sub = makeSubway(); // creates a subway object in frame 1

    // RIPPLES IN FRAME 1
    // boundaries for ripples in frame 1
    var top = 212; // top boundary
    var bottom = height; // bottom boundary
    // first ripples that come into frame 1
    for (var i = 0; i < 10; i++) {
        var rippleX = random(width);
        var rippleY = random(top, bottom);
        ripples[i] = makeRipples(rippleX, rippleY);
    }
}

function draw(){
    // FRAME 1
    f1scene(); // the sky
    // moving the subway
    sub.move();
    sub.draw();
    // moving the ripples
    for (var i = 0; i < ripples.length; i++) {
        ripples[i].move();
        ripples[i].draw();
    }
    removeRipple();
    addRipple(); 


    // FRAME 2
    f2scene(); // background in frame 2
    // moving the shooting stars
    for (var i = 0; i < shootingStarArray.length; i++) {
        shootingStarArray[i].move();
        shootingStarArray[i].draw();
    }
    removeShootingStar(); // keeps shooting stars that are in frame
    addShootingStar(); // adds shooting stars when mouse is clicked
    f2car(); // subway car features in frame 2
    astroboy(); // astronaut boy in frame 2


    // FRAME 3
    f3scene(); // background in frame 3


    // TEXT
    // words in frame 1
    var f1text = "every night i take the subway home..."
    // words in frame 2
    var f2text = "i wonder..."
    // words in frame 3
    var f3text = "if our worlds will ever collide again."
    noStroke();
    fill("white");
    textSize(14);
    textStyle(ITALIC);
    text(f1text, f1x + 10, 279); // frame 1 text
    text(f2text, 490, 87); // frame 2 text
    text(f3text, f1x + f1width + 25, 279); // frame 3 text


    // BORDERS AROUND THE FRAMES
    noStroke();
    fill(27, 34, 45);
    rect(0, 0, width, f1y); // top border
    rect(0, 0, f1x, height); // border left of frame 1
    rect(f1x + f1width, 0, 17, height); // border right of frame 1
    rect(0, 0, f1x + f1width, f1y); // border above frame 1
    // border below frame 1
    rect(0, f1y + f1height, width, width - f1y - f1height);
    // border below frame 2
    rect(f1x + f1width, f1y + f2height, width - f1x - f1width, f2spacing);
    // border right of frame 2
    rect(f1x + f1width + f1spacing + f2width, 0, 
        width - f1x + f1width + f1spacing + f2width, height);
}

// ---------------- FUNCTIONS & OBJECTS FOR FRAME 1 ------------------

// FRAME 1 BACKGROUND
function f1scene(){
    // GRADIENT SKY
    noFill();
    for (var s = f1y; s < f1y + f1height; s++) {
        var skyInter = map(s, f1y, f1y + f1height, 0, 1);
        var skyStroke = lerpColor(skyBlue, skyYellow, skyInter);
        stroke(skyStroke);
        line(f1x, s, f1x + f1width, s);
    } 
    planets(); // planets in the sky
    surface(); // surface of the moon
    clouds(); // clouds in the sky
    constellations(); // constellations in the sky 

    // TWINKLING STARS
    fill(242, 242, 158);
    for (var st = 0; st < 8; st++) {
        // x positions for the twinkling stars
        starX = [32, 77, 129, 177, 190, 205, 242, 276];
        // y positions for the twinkling stars
        starY = [91, 66, 63, 27, 79, 53, 25, 90];
        // sizes for the twinkling stars
        starSize = [5, 4, 4, 5, 4, 5, 4, 5];
        star(starX[st], starY[st], 
             starSize[st] - random(1, 3), starSize[st], 5);
    }

    // SUBWAY TRACK
    stroke(79, 94, 94);
    fill(130, 142, 134);
    // pillars holding the track
    for (var i = 0; i < 6; i++) {
        rect(34 + i * 48, 148, 14, 67);
    }
    rect(0, 148, f1x + f1width, 13); // bridge above the water

    // GRADIENT WATER
    noFill();
    for (var w = 212; w < f1y + f1height; w++) {
        var waterInter = map(w, 212, f1y + f1height, 0, 1);
        var waterStroke = lerpColor(waterYellow, waterBlue, waterInter);
        stroke(waterStroke);
        line(f1x - 1, w, f1x + f1width, w);
    }
}

// CONSTELLATIONS iN FRAME 1
function constellations() {
    stroke(131, 178, 177); 
    strokeWeight(1);

    // LIBRA CONSTELLATION
    // the following lines join together to create libra
    line(98.5, 90.5, 98.5, 84.5);
    line(98.5, 84.5, 89.5, 70.5);
    line(89.5, 70.5, 111.5, 60.5);
    line(111.5, 60.5, 112.5, 74.5);
    line(89.5, 70.5, 96.5, 56.5);
    line(96.5, 56.5, 111.5, 60.5);

    // LEO CONSTELLATION
    // the following lines join together to create leo
    line(146, 84, 142, 75);
    line(142, 75, 154, 79);
    line(154, 79, 146, 84);
    line(146, 84, 148, 97);
    line(148, 97, 156, 95);
    line(156, 95, 156, 89);
    line(156, 89, 161, 88);
    line(161, 88, 172, 95);
    line(172, 95, 169, 100);

    // AQUARIUS CONSTELLATION
    // the following lines join together to create aquarius
    line(258, 49, 241, 63);
    line(241, 63, 246, 65);
    line(246, 65, 254, 63);
    line(241, 63, 241, 67);
    line(241, 67, 239, 69);
    line(239, 69, 247, 83);
    line(247, 83, 249.5, 77.5);
    line(249.5, 77.5, 258, 76);
    line(258, 76, 268, 82);

}

// CLOUDS IN FRAME 1
function clouds() {
    noStroke();

    // YELLOW CLOUDS
    fill(210, 216, 130, 70);
    var ycloudx = [92, 67, 103, 117, 122, 159]; // x coordinates
    var ycloudy = [92, 88, 53, 56, 52, 70]; // y coordinates
    var ycloudw = [56, 48, 27, 35, 19, 25]; // cloud width
    var ycloudh = [9, 8, 5, 4, 3.5, 3]; // cloud height
    // for loop generates 6 yellow clouds
    for (var y = 0; y < 6; y++) {
        ellipse(ycloudx[y], ycloudy[y], ycloudw[y], ycloudh[y]);
    }

    // PINK CLOUDS
    fill(242, 136, 158, 150);
    var pcloudx = [251, 65, 48, 183, 196, 212]; // x coordinates
    var pcloudy = [109, 58, 55, 43, 46, 41]; // y coordinates
    var pcloudw = [80, 30, 25, 35, 31, 29]; // cloud width
    var pcloudh = [12, 7, 3, 4, 7, 9]; // cloud height
    // for loop generates 6 pink clouds
    for (var p = 0; p < 6; p++) {
        ellipse(pcloudx[p], pcloudy[p], pcloudw[p], pcloudh[p]);
    }
}

// SURFACE OF THE MOON IN FRAME 1
function surface() {
    strokeWeight(1);
    stroke(31, 73, 72);
    fill(38, 104, 119);

    // x positions of the moon surface's shape
    var moonx = [f1x, 61, 107, 152, 202, 248, f1x + f1width, 
                 f1x + f1width, f1x];
    // y positions of the moon surface's shape
    var moony = [187, 185, 191, 180, 188, 190, 195, 237, 237];

    // SURFACE OF THE MOON
    beginShape(); 
    vertex(moonx[0], moony[0]);
    // for loop for curved parts of the shape
    for (var m = 0; m < 7; m++) {
        curveVertex(moonx[m], moony[m]);
    }
    // straight parts of the moon surface shape
    // these points can't be seen because they are
    // blocked by the water
    vertex(moonx[7], moony[7]);
    vertex(moonx[8], moony[8]);
    vertex(moonx[0], moony[0]);
    endShape();

    // MOON CRATERS
    noStroke();
    fill(22, 81, 91);
    ellipse(58, 192, 29, 6);
    ellipse(96, 202, 19, 3);
    ellipse(146, 188, 19, 4);
    ellipse(201, 201, 20, 3);
    ellipse(241, 200, 34, 5);
}

// PLANETS IN THE SKY OF FRAME 1
function planets () {
    // LARGEST PLANET
    strokeWeight(2);
    stroke(30, 76, 114);
    fill(32, 111, 142);
    ellipse(217, 164, 142, 142);

    // SECOND LARGEST PLANET
    strokeWeight(1);
    stroke(24, 76, 119);
    fill(18, 114, 130, 95);
    ellipse(95, 119, 75, 75);

    // RINGED PLANET
    noStroke();
    fill(234, 106, 124);
    ellipse(63.5, 45, 51, 12); // rings
    strokeWeight(0.5);
    stroke(140, 65, 83);
    fill(242, 136, 158);
    ellipse(64, 44, 25, 25); // planet itself

    // CRESCENT MOON
    strokeWeight(1);
    stroke(234, 96, 119);
    fill(242, 242, 158);
    ellipse(144.8, 40, 30, 30); // crescent part
    noStroke();
    fill(31, 94, 104);
    ellipse(143, 37, 24, 24); // shadow part

}

// MAKING THE STARS IN FRAME 1 + 3
// called in f1scene() and f3scene()
function star(x, y, radius1, radius2, npoints) {
    var angle = TWO_PI / npoints;
    var halfAngle = angle / 2.0;
    beginShape();
    for (let 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);
}

// ------------- FUNCTIONS & OBJECTS FOR FRAME 2 -------------------

// FRAME 2 BACKGROUND
function f2scene() {
    // WINDOW BEHIND THE RIDER
    strokeWeight(4);
    stroke(255);
    fill(9, 74, 89);
    rect(302, 29, 291, 85);

    // NIGHTTIME SCENERY
    // stars that come into frame when the subway is "moving"
    noStroke();
    fill(242, 242, 158);
    for (var i = 0; i < subwayStarArray.length; i++) {
        subwayStarArray[i].move();
        subwayStarArray[i].draw();
    }
    removeSubwayStar(); // keeps stars in the keepSubwayStar array
    addSubwayStar(); // based on a small probability, adds new stars

    // big planet
    strokeWeight(2);
    stroke(30, 76, 114);
    fill(32, 111, 142);
    ellipse(planetx, 100, 130, 130); 
    planetx += 0.05 // planet slowly moves right as time passes

    // MORE WINDOW FEATURES
    // glass dividers on the subway windows
    strokeWeight(3);
    stroke(255);
    var divideh = 24; // height of vertical dividers
    var dividex = 335; // initial x position of vertical dividers
    var dividey = 32; // y position of all vertical dividers
    var dividespace = 70; // horizontal spacing in between
    // 4 vertical dividers are created through lines
    for (var d = 0; d < 4; d++) {
        line(dividex + dividespace * d, dividey,
             dividex + dividespace * d, dividey + divideh);
    }
    // horizontal line beneath the vertical dividers
    line(302, 32 + divideh, 302 + f2width, 32 + divideh);

    // window reflections
    noStroke();
    fill(253, 255, 255, 40);
    // first reflection shape
    beginShape();
    vertex(330, 112);
    vertex(326, 95); 
    vertex(381, 31);
    vertex(399, 31);
    vertex(330, 112);
    endShape();
    // second reflection shape
    beginShape();
    vertex(355, 95);
    vertex(409, 31);
    vertex(418, 31);
    vertex(364, 95);
    vertex(355, 95);
    endShape();
    // third reflection shape
    beginShape(); 
    vertex(423, 98);
    vertex(472, 30);
    vertex(509, 30);
    vertex(465, 98);
    vertex(423, 98);
    endShape();
    // fourth reflection shpae
    beginShape();
    vertex(512, 102);
    vertex(555, 31);
    vertex(572, 31);
    vertex(531, 102);
    vertex(512, 102);
    endShape();
}

// FEATURES OF THE SUBWAY CAR IN FRONT OF THE WINDOW
function f2car() {
    // subway car wall above the window
    noStroke();
    fill(143, 169, 183);
    rect(f1x + f1width + 10, 0, f2width, 29);
    // subway car wall below the window
    rect(f1x + f1width + 10, 114, f2width, 40);

    // subway chairs
    // back of the chair that the rider leans against
    stroke(73, 122, 121);
    strokeWeight(1);
    fill(174, 199, 206);
    rect(320, 92, 247, 77, 15); 

    // indents in the chair 
    noStroke();
    fill(153, 181, 188); 
    var indentx = 333; // initial x positions of indents
    var indenty = 103; // y positions of indents
    var indentw = 66; // width of indents
    var indenth = 65; // height of indents
    var indentround = 15; // roundness of indents
    var indentspacing = 79; // spacing between each indent
    // for loop creates 3 evenly spaced indents in the chair 
    for (var c = 0; c < 3; c++) {
        rect(indentx + indentspacing * c, indenty, indentw, 
             indenth, indentround);
    }

    // handles above the window
    noFill();
    strokeWeight(3);
    stroke(200, 214, 219);
    var handlespacing = 82; // horizontal spacing between handles
    // for loop creates 3 evenly spaced handles
    for (var h = 0; h < 3; h++) {
        ellipse(360 + handlespacing * h, 20, 10, 40);
    }
}

// ASTRONAUT BOY SITTING IN THE SUBWAY
function astroboy() {
    // arms
    noStroke();
    fill(160, 116, 87);
    rect(397, 137, 13, 15); // right arm

    // shirt
    fill(194, 160, 224);
    ellipse(379, 118.5, 66, 19); // shoulders
    rect(356, 117, 47, 35); // body
    rect(346, 119, 15, 19); // left sleeve
    ellipse(354, 137.5, 16, 5); // bottom of left sleeve
    rect(400, 119, 12, 19); // right sleeve
    ellipse(404, 137.5, 16, 5); // bottom of right sleeve
    // pocket on shirt
    fill(234, 132, 132); 
    rect(385, 130, 11, 13); 
    ellipse(390, 143, 11, 3);

    // right arm
    noStroke();
    fill(160, 116, 87);
    quad(346, 138, 360, 138, 366, 150, 352, 150); // left arm

    // astronaut helmet
    // neck piece
    noStroke();
    fill(100);
    ellipse(377, 111, 27, 6);
    rect(364, 100, 27, 11);
    // helmet
    strokeWeight(1);
    stroke(184, 209, 208);
    fill("white");
    ellipse(377, 83, 48, 48);
    // glass piece
    noStroke();
    fill(33, 51, 68);
    ellipse(376, 95.5, 34, 11);
    quad(357, 85, 395, 85, 393, 96, 359, 96);
    ellipse(376, 85, 38, 11);
    // highlights on glass piece
    fill(100, 107, 109);
    ellipse(371, 84, 22, 2); // top highlight
    ellipse(376, 98, 18, 1); // bottom highlight
}

// ------------------ FUNCTIONS/OBJECTS IN FRAME 3 ---------------------

// FRAME 3 BACKGROUND
function f3scene() {
    // the dark night sky
    noStroke();
    fill(18, 38, 76);
    rect(307, 12 + f2height + f2spacing, f2width, f2height); 

    // clouds
    // darkest clouds
    fill(39, 49, 117, 170);
    ellipse(382, 193, 69, 48);
    ellipse(534, 201, 95, 47);
    // purple clouds
    fill(118, 86, 153, 120);
    ellipse(348, 230, 107, 71);
    ellipse(445, 220, 142, 77);
    ellipse(531, 225, 98, 52);
    // darker pink clouds
    fill(219, 127, 154, 130);
    ellipse(374, 247, 76, 50);
    ellipse(520, 251, 135, 50);

    // glow behind the star in figure's hand
    noStroke();
    var glowx = 491; // x position of the glow center
    var glowy = 216; // y position of the glow center 
    // controls how the glowing portion of the star 
    // grows and shrinks, so it looks like it's flickering
    var osc = 10 + sin(millis()) * 1;
    // outer glow
    fill(239, 125, 172, 100);
    ellipse(glowx, glowy, 20 + osc, 20 + osc);
    // middle glow
    fill(249, 155, 189, 120);
    ellipse(glowx, glowy, 10 + osc, 10 + osc);
    // inner glow
    fill(237, 102, 138);
    ellipse(glowx, glowy, 4 + osc, 4 + osc);

    starfigure(); // mysterious figure in the clouds

    // light pink clouds
    noStroke();
    fill(242, 165, 165, 200);
    ellipse(337, 273, 76, 50);
    ellipse(535, 276, 94, 50);
    fill(242, 165, 165); // cloud covering the figure is opaque
    ellipse(430, 278, 135, 50);


    // twinkling stars
    fill(242, 242, 158);
    for (var st = 0; st < 5; st++) {
        // x positions for the twinkling stars
        starX = [366, 413, 491, 493, 514];
        // y positions for the twinkling stars
        starY = [240, 213, 216, 245, 178];
        // sizes for the twinkling stars
        starSize = [8, 9, 6, 8, 6];
        star(starX[st], starY[st], 
             starSize[st] - random(4, 5), starSize[st], 5);
    }
}

function starfigure() {
    // body
    fill(224, 184, 140);
    ellipse(466, 195.5, 2, 5); // right ear
    ellipse(443, 194.5, 2, 5); // left ear
    rect(450, 203, 8, 9); // neck
    quad(470, 235, 485, 219, 490, 220, 475, 240); // arm
    ellipse(488.5, 219.5, 7, 3); // palm
    //forefinger
    beginShape();
    vertex(491, 220);
    vertex(491, 218);
    vertex(494.2, 217.6);
    vertex(494.5, 218.5);
    vertex(492, 220);
    vertex(491, 220);
    endShape();
    ellipse(494.5, 216.5, 1, 4);// upper finger

    //hair
    fill(248, 252, 195);
    ellipse(454.5, 194, 23, 24);
    hairx = [443, 466, 464, 463, 462, 452, 450, 449, 445, 445, 
             444, 441, 443, 443]; // x positions of hair coordinates
    hairy = [194, 194, 208, 205, 208, 208, 206, 208, 207, 205, 
             207, 207, 199, 194]; // y positions of hair coordinates
    beginShape();
    for (var h = 0; h < 14; h++) {
        vertex(hairx[h], hairy[h]);
    }
    endShape();

    // cape
    fill(30, 30, 124);
    ellipse(454, 217, 35, 13);
    quad(426, 266, 437, 218, 472, 218, 482, 266);
    // folds in the cape
    fill(16, 16, 94);
    triangle(438, 259, 443, 221, 443, 259);
    triangle(467, 260, 465, 222, 472, 260);
    // constellations of the cape
    strokeWeight(1);
    stroke(113, 108, 183);
    // first constellation
    line(443, 216, 448, 224);
    line(448, 224, 452, 225);
    line(452, 225, 445, 235);
    // second constellation
    line(455, 236, 453, 244);
    line(453, 244, 459, 246);
    line(459, 246, 461, 242);
    line(461, 242, 465, 250);
    // constellation on the edge of the cape
    line(432, 243, 434, 245);
    line(434, 245, 429, 251);
}

// ------------- FUNCTIONS & OBJECTS FOR THE MOVING SUBWAY IN FRAME 1 -------------

//  PRESSING KEYS TO CONTROL SUBWAY CAR SPEED
function keyPressed() {
    // everytime the "f" key is pressed, the subway car's 
    // speed will increase by 1
    if (key == "f") {
        accelerate += 1;
    }

    // likewise, everytime "s" is pressed, the subway car's
    // speed will reduce by 1
    if (key == "s") {
        accelerate -= 1; 
    }

    // upon pressing the r key, it resets the accelerate to 0
    // helpful in case you make the train way too fast and don't
    // want to click s multiple times to get back to the original speed
    if (key === "r") {
        accelerate = 0; 
    }
}

// SUBWAY OBJECT
function makeSubway() {
    var subwaycar = {x: -200,
                     y: 119,
                     speed: 4,
                     move: moveSubway,
                     draw: drawSubway}
    return subwaycar; 
}

function drawSubway() {
    // subway cars
    var sublength = 75; // length of subway car
    var subheight = 28; // height of subway car
    var subx = -200; // x position of subway car
    var suby = 119; // y position of subway car
    var round = 7.5; // rounded edges of rect

    // subway car windows
    var windowY = 125; // y position of subway window
    var windowW = sublength / 4 // length of subway window
    var windowH = 10; // height of subway window
    var wspace = 4.5; // spacing between subway windows

    // creating the subway car
    for (var s = 0; s < 5; s++) {
        stroke(125, 121, 132);
        fill(230, 230, 252); 
        rect(this.x + sublength * s, suby, sublength, subheight, round);
        for (var i = 0; i < 3; i++) {
            fill(21, 68, 76);
            rect(this.x + wspace * (i + 1) + windowW * i + sublength * s, 
                windowY, windowW, windowH);
        }
    }
}

function moveSubway() {
    this.x += (this.speed + accelerate); 
    // to prevent the subway car from moving backwards, 
    // if accelerate becomes too big that its absolute value
    // is greater than the speed, it resets to 0, which means
    // the subway train will pause right before and upon pressing
    // the s key again, it will reset to the original speed
    if (accelerate < this.speed * -1) {
        accelerate = 0;  
    }
    // reset the x position of the last subway car to -500
    // if the last subway car exits the frame
    if (this.x > f1x + f1width) {
        this.x = -500; 
    }
}

// ----------- FUNCTIONS & OBJECTS FOR FALLING STARS IN FRAME 1 & 2 ----------

// FALLING STARS IN FRAME 1 & 2 WHEN MOUSE IS PRESSED
function mousePressed() {
    // when mouse is pressed, the function will 
    // to add a shooting star will be called with 
    // the x and y inputs of the mouse position
    if (mouseX < width && mouseX > f1x &&
        mouseY < f1y + f1height && mouseY > f1y) {
        addShootingStar(mouseX, mouseY);
    }
}

// SHOOTING STAR OBJECT 
function makeShootingStar(xPos, yPos) {
    var shootingStar = {x: xPos,
                        y: 0, 
                        size: random(7, 20),
                        speed: random(3, 8),
                        move: moveShootingStar,
                        draw: drawShootingStar}
    return shootingStar; 
}

// DRAWING THE SHOOTING STAR
function drawShootingStar() {
    // controls how the glowing portion of the star 
    // grows and shrinks, so it looks like it's flickering
    var osc = 10 + sin(millis()) * 1;

    noStroke();

    // glowing part of the star
    fill(244, 242, 168, 75);
    ellipse(this.x, this.y, this.size + osc, this.size + osc);

    // inner part of the star
    fill(239, 235, 91);
    ellipse(this.x, this.y, this.size, this.size);
    
}

// MOVING THE SHOOTING STAR
function moveShootingStar() {
    this.y += this.speed; 
}

// ADDING SHOOTING STARS
function addShootingStar(xPos, yPos) {
    shootingStarArray.push(makeShootingStar(xPos, yPos));
}

// REMOVING SHOOTING STARS 
function removeShootingStar() {
    // array for keeping the stars
    var keepStar = [];
    // as long as the shooting stars are in bound of frame 1
    // they will be pushed into the array for keeping the stars
    for (var i = 0; i < shootingStarArray.length; i++) {
        if (shootingStarArray[i].y < f1y + f1height + 
            shootingStarArray[i].size) {
            keepStar.push(shootingStarArray[i]);
        }
    }
    shootingStarArray = keepStar;  
}

// ------------- FUNCTIONS & OBJECTS FOR THE RIPPLES IN FRAME 1 --------------

// RIPPLE OBJECT
function makeRipples(xPos, yPos) {
    var makeRipple = {x: xPos,
                      y: yPos,
                      // longer ripples are in the front, shorter ones in the back
                      length: map(yPos, 212, height, 5, 75),
                      // thinner ripples in the back, thicker ones in the front
                      weight: map(yPos, 212, height, 1, 4),
                      // faster ripples in the front, slower ripples in the back
                      speed: map(yPos, 212, height, 0.5, 1),
                      move: moveRipple,
                      draw: drawRipple}
                    return makeRipple; 
}

// MOVING THE RIPPLE
function moveRipple() {
    // x position changes by speed
    this.x += this.speed; 
    // if the ripple leaves the frame, reset x position
    // to the left side of the frame
    if (this.x > width + this.length) {
        this.x === -this.length;
    }
}

// ADDING RIPPLES
// using a tiny probability, add ripples
function addRipple() {
    if (random(0, 1) < 0.025) {
        ripples.push(makeRipples(-75, random(212, height)));
    }
}

// REMOVING RIPPLES
function removeRipple() {
    // an array for ripples to keep
    var keepRipples = [];
    // as long as ripples are within the bounds of frame 1, 
    // keep them in the keepRipples array
    for (var i = 0; i < ripples.length; i++) {
        if (ripples[i].x < f1x + f1width) {
            keepRipples.push(ripples[i]);
        }
    }
    ripples = keepRipples;
}

// DRAWING THE RIPPLE
function drawRipple() {
    strokeWeight(this.weight);
    stroke(255, 255, 255, 75);
    line(this.x, this.y, this.x + this.length, this.y);
}

// ------------- FUNCTIONS & OBJECTS FOR THE STARS IN FRAME 2 -------------

// SUBWAY STAR OBJECT
function makeStar(xPos, yPos) {
    var subwayStar = {x: xPos,
                      y: yPos,
                      radius1: random(5, 10),
                      npoints: 5,
                      speed: random(0.5, 2),
                      move: moveSubwayStar,
                      draw: drawSubwayStar}
                    return subwayStar; 
}

// MOVING THE SUBWAY STARS
function moveSubwayStar() {
    // x position changes by speed
    this.x += this.speed; 
    // if the star leaves the frame, reset x position
    // to the left side of the frame
    if (this.x > width) {
        this.x === f1x + f1width + 10;
    }
}

// ADDING SUBWAY STARS
// using a tiny probability, add subway stars
function addSubwayStar() {
    if (random(0, 1) < 0.02) {
        subwayStarArray.push(makeStar(f1x + f1width + 10, 
                             random(30, 100)));
    }
}

// REMOVING SUBWAY STARS
function removeSubwayStar() {
    // an array for subway stars to keep
    var keepSubwayStar = [];
    // as long as the stars are within the width, 
    // keep them in a separate array
    for (var i = 0; i < subwayStarArray.length; i++) {
        if (subwayStarArray[i].x < width) {
            keepSubwayStar.push(subwayStarArray[i]);
        }
    }
    subwayStar = keepSubwayStar;
}

// DRAWING THE SUBWAY STARS
function drawSubwayStar() {
    fill(242, 242, 158);
    var angle = TWO_PI / this.npoints;
    var halfAngle = angle / 2.0;
    beginShape();
    for (let a = 0; a < TWO_PI; a += angle) {
        var sx = this.x + cos(a) * (this.radius1 - 5);
        var sy = this.y + sin(a) * (this.radius1 - 5);
        vertex(sx, sy);
        sx = this.x + cos(a + halfAngle) * this.radius1;
        sy = this.y + sin(a + halfAngle) * this.radius1;
        vertex(sx, sy);
    }
  endShape(CLOSE);
}



For my final project, I created a speculative cartoon panel. It’s speculative in the sense that the it forces the viewer to use their imagination to weave a story of what might have happened–the possibilities are endless. In this project, I enjoyed exploring my interests in illustration, concept art, and storytelling. To convey this dreamy, mysterious, magical atmosphere, I worked within a range of cool/teal tones, with pink and yellow highlights.

To begin, I created a moodboard of images/animations on Pinterest. Then, I sketched out/digitized my idea using simple shapes on Illustrator. Not only did I enjoy creating the static images, I think programming the interactions made the comic scene much more fun and engaging.

Moodboarding: I drew a lot of inspiration from space/water concept art. What I love about concept art is its ability to inspire your imagination as you create stories in your head about the piece.
My sketch on Illustrator, which helped save time when visually styling the scene.

Leave a Reply