# 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.

``````/*
* 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();

// 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
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(){
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

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()
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

// 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) {
}
}

// 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;
}

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;
}
}

// using a tiny probability, add ripples
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,
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;
}
}

// using a tiny probability, add subway stars
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.