sketch

//Steven Fei & Mike Jin
//Section A & C
//Final Project
//zfei@andrew.cmu.edu & fjin@andrew.cmu.edu
var starNumber = 150;//number of the stars on the background
var starsize = 1.5;//size of the stars
var sx = [];//array to define the x position of the stars
var sy = [];//array to define the y position of the stars
var sz = [];//array to define the z position of the stars
var amplitude = 3.14 * 3;//define the moving margin of the stars
var waveSpeed;//define the moving speed of the stars on the background
var theta = 0;//define the moving angle of the stars
var glowDefiner = [];//define the true false value for whether to let the star glow
var glowSize = 22;//glowing size of the stars
var newStars = [];//array for making new stars
var mouseXList = [];//arrays to store mouseX value
var mouseYList = [];//arrays to store mouseY value
var img; //load image for the earth texture mapping 
var w = 600 / 7 // devivded the canvas into seven regions and from left to right, the pitches of the piano sound will progressively become higher  
var mySndC; //Piano note C
var mySndD; //Piano note D
var mySndE; //Piano note E
var mySndF; //Piano note F
var mySndG; //Piano note G
var mySndA; //Piano note A
var mySndB; //Piano note B
var newExplod = [];//array for making new explosion at the background
var mouseXListEx = [];//arrays to store mouseX value
var mouseYListEx = [];//arrays to store mouseY value

function preload(){
//coded by Mike
//preload the soundtrack of each piano notes to the file
    mySndC = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/c-1.wav");
    mySndD = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/d-1.wav");
    mySndE = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/e-1.wav");
    mySndF = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/f-1.wav");
    mySndG = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/g-1.wav");
    mySndA = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/a-1.wav");
    mySndB = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/b-1.wav");
    mySndC.setvolume(1);
    mySndD.setvolume(1);
    mySndE.setvolume(1);
    mySndF.setvolume(1);
    mySndG.setvolume(1);
    mySndA.setvolume(1);
    mySndB.setvolume(1);
}

function setup() {
//load the background image for the texture mapping of the earth
//coded by Mike
    img = loadImage("https://i.imgur.com/lamlO83.jpg");
    createCanvas(600, 600,WEBGL);

//create values for the positions of the stars on the background
//coded by Steven
    for (var i = 0; i < starNumber; i++){
        sx.push(random(-width * 0.75, width * 0.75));
        sy.push(random(-height, height));
        sz.push(random(-width, height/2));
        var toggle = random(1.0);
        //define whether the stars on the background will glow
        if(toggle < 0.9){
            glowDefiner.push(false);
        }else{
            glowDefiner.push(true);
        }
    }
    for(var j = 0; j < glowDefiner.length; j++){
    print(glowDefiner[j]);
    }
}

function draw(){
    background(0);
    noStroke();
    normalMaterial();
    centerCube();//create a center star to give a sense of what perspective we are looking at
    makeCamera();//use the makeCamera function to change the viewport angle
    makeearth();
    push();
    //draw the stars on the background
    for(var i = 0; i < starNumber; i++){
        //coded by Steven
        push();
        waveSpeed = map(sz[i], -width, height/2, 15000, 60000);//define the moving speed of the stars
        theta += (TWO_PI / waveSpeed);//define the moving angle of the stars
        if(theta > amplitude){
            theta = -theta;//set the moving margins of the stars
        }
        sy[i] += sin(theta);//set the moving value to the positions
        sx[i] += cos(theta);//set the moving value to the positions
        translate(sx[i], sy[i], sz[i]);
        //coded by Mike
        if(glowDefiner[i]){
            fill(255, 200, 130, 4);
            sphere(glowSize);//draw glow light of the sphere
        }
        fill("white");
        smooth();
        sphere(starsize);//draw the stars
        pop();
    }
    pop();

    push();
    //make the planet
    if (mouseXListEx.length != 0){
        for(var k = 0; k < newExplod.length; k++){
            newExplod[k].updateExplo();//animate the expansion of the stars
            push();
            translate(newExplod[k].x, newExplod[k].y,0);
            rotateX(frameCount * 0.05 + k*2);//rotate the new star
            rotateY(frameCount * 0.05 + k*2);//rotate the new star
            newExplod[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newExplod.length > 2){
        newExplod.shift();
    }
    pop();

    push();
    // make the explosion
    if (mouseXList.length != 0){
        for(var k = 0; k < newStars.length; k++){
            newStars[k].updateStar();//animate the expansion of the explosion in the background 
            push();
            translate(newStars[k].x, newStars[k].y,0);
            newStars[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newStars.length > 4){
        newStars.shift();
    }
    pop();
    
}

function makeCamera(){
//coded by Steven
    camX = map(mouseX, 0, width, -width/2, width/2);//changing camera position x
    camY = map(mouseY, 0, height, -height/2, height/2);//changing camera position y
    camZ = height/2;//changing camera position z
    camera(camX, camY, camZ,0,0,0,1,1,0);//allow the viewport angle to change
}

//make object to create new stars
function makeNewStar(x, y, radius){
//coded by Steven
    var newstar = {x: x,
                    y: y,
                    r: radius,
                    updateStar: updateStar,
                    draw: drawNewStar};
    return newstar;
}

function makeNewExplo(x, y, radius){
//coded by Mike
    var newExplo = {x: x,
                    y: y,
                    r: radius,
                    updateExplo: updateExplo,
                    draw: drawNewExplo};
    return newExplo;
}

//function to draw new star
function drawNewStar(){
//coded by Mike
    var color1 = random(150, 255);
    var color2 = random(100,180);
    var color3 = random(100,200);
    var density = random(14,20);//allow different numbers of the spheres to appear on the star
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX = this.r * sin(lengthValue) * cos(widthValue);
            var pY = this.r * sin(lengthValue) * sin(widthValue);
            var pZ = this.r * cos(lengthValue);
            push();
            fill(color1, color2, color3);
            translate(pX, pY, pZ);
            sphere(1.6);
            pop();
        }
    }
}

function drawNewExplo(){
//coded by Mike
    var color4 = random(100, 255);
    var color5 = random(100,180);
    var color6 = random(100,200);
    var density = random(12, 15);//allow different numbers of the spheres to appear for the explosion
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX1 = this.r * sin(lengthValue) * cos(widthValue * 0.5) * 0.5;
            var pY1 = this.r * sin(lengthValue * 0.5) * sin(widthValue) * 0.5;
            var pZ1 = this.r * cos(lengthValue);
            push();
            fill(color4, color5, color6);
            translate(pX1, pY1, pZ1);
            box(2, 2, 2);
            pop();
        }
    }
}
function updateExplo(){
//coded by Mike
    this.r += random(1,2);//allow the new explosion to expand
}

function updateStar(){
//coded by Mike
    this.r += random(0.5,2);//allow the new star to expand
}
function mousePressed(){
//coded by Steven
    var newStarMaking = [];//empty list for the making new star when mouse is pressed
    var newMouseXList = [];
    var newMouseYList = [];
    var newExploMaking = [];
    var newmouseXListEx = [];
    var newmouseYListEx = [];
    var clickEx;//check whether there is existing new stars
    var click;//check whether there is existing new stars
    
    if(mouseXList.length == 0){
        click = 0;//count whether the times of starting the object
        newStarMaking.push(newStars[0]);//assign values to new arrays to store valid value
        newMouseXList.push(mouseXList[0]);//assign values to new arrays to store valid value
        newMouseYList.push(mouseYList[0]);//assign value to new arrays to store valid value
    }
    else{
        //define the initiating position according to the mouse position
        for(var l = 0; l < newStars.length; l++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newStars[l].x, newStars[l].y);
            if(distance <= 30){
                click = 1;
            }else{
                click = 0;
                newStarMaking.push(newStars[l]);//assign values to the new array
                newMouseXList.push(mouseXList[l]);//assign values to the new array
                newMouseYList.push(mouseYList[l]);//assign values to the new array
            }
        }
        //get the valid value back to the list
        newStars = newStarMaking;
        mouseXList = newMouseXList;
        mouseYList = newMouseYList;
    }
    //avoid invalid value
    if(click == 0){
        mouseXList.push(mouseX - width/3);
        mouseYList.push(mouseY - width/3);
        var newStar = makeNewStar(mouseX - width/3, mouseY-width/3, 30);
        newStars.push(newStar);
    }

    //add value to empty list
    if(mouseXListEx.length == 0){
        clickEx = 0;
        newExploMaking.push(newExplod[0]);
        newmouseXListEx.push(mouseXListEx[0]);
        newmouseYListEx.push(mouseYListEx[0]);
    }
    else{
    //assign initiating position according to the mouse postion
        for(var w = 0; w < newExplod.length; w++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newExplod[w].x, newExplod[w].y);
            if(distance <= 30){
                clickEx = 1;
            }else{
                clickEx = 0;
                newExploMaking.push(newExplod[w]);
                newmouseXListEx.push(mouseXListEx[w]);
                newmouseYListEx.push(mouseYListEx[w]);
            }
        }
        //assign values back to the list
        newExplod = newExploMaking;
        mouseXListEx = newmouseXListEx;
        mouseYListEx = newmouseYListEx;
    }
    //avoid invalid value
    if(clickEx == 0){
        mouseXListEx.push(mouseX - width/3);
        mouseYListEx.push(mouseY - width/3);
        var newExplo = makeNewExplo(mouseX - width/3, mouseY-width/3, 300);
        newExplod.push(newExplo);
    }

    //coded by Mike
    //load the sound and defines the regions of the sound 
    if(mouseX > 0 & mouseX < w){
            mySndC.play();
        }
        if(mouseX > w & mouseX < 2 *w){
            mySndD.play();   
        }
        if(mouseX > 2 * w & mouseX < 3 * w){
            mySndE.play();
        }
        if(mouseX > 3 * w & mouseX < 4 * w){
            mySndF.play();
        }
        if(mouseX > 4 * w & mouseX < 5 * w){
            mySndG.play();
        }
        if(mouseX > 5 * w & mouseX < 6 * w){
            mySndA.play(); 
        }
        if(mouseX > 6 * w & mouseX < 7 * w){
            mySndB.play(); 
        }
}


//function to make a center planet to have some understanding of the perspective
//coded by Mike
function centerCube(){
    //make sure the location of the center planet is always at the center of the canvas
    push();
    var locX = mouseX - height / 2;
    var locY = mouseY - width / 2;
    ambientLight(50);
    directionalLight(255, 0, 0, 0.25, 0.25, 0);
    pointLight(0, 0, 255, locX, locY, 250);
    ambientMaterial(100);
    strokeWeight(0.5);
    stroke(255);
    smooth();
    sphere(40);
    pop();
    //first ring surronding the planet
    push();
    rotateZ(frameCount * 0.01);
    rotateX(frameCount * 0.01);
    rotateY(frameCount * 0.01);
    strokeWeight(0.5);
    smooth();
    stroke(255);
    torus(60, 0.5);
    pop();
    //second ring surronding the planet
    push();
    rotateZ((100+ frameCount) * 0.01);
    rotateX((100 + frameCount) * 0.01);
    rotateY((100+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(70, 0.5);
    pop();
    //third ring surronding the planet
    push();
    rotateZ((200+ frameCount) * 0.01);
    rotateX((200 + frameCount) * 0.01);
    rotateY((200+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(80, 0.5);
    pop();
    //fourth ring surronding the planet
    push();
    rotateZ((300+ frameCount) * 0.01);
    rotateX((300 + frameCount) * 0.01);
    rotateY((300+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(90, 1);
    pop();
}
//function to make a earth adjacent to the center planet 
//coded by Mike and Steven 
function makeearth(){
    push();
    translate(width / 2, height / 3, -150);
    rotateX(frameCount * 0.05);
    rotateY(frameCount * 0.05);
    texture(img);
    sphere(20);
    pop();
}

Mihika Bansal – Final Project

sketch

//Mihika Bansal 
//mbansal@andrew.cmu.edu 
//Section E 
//Project 12

var ripples = []; 
var color = []; 
var b = 238;
var g = 238;  
//color for background 


function setup() {

    createCanvas(480, 480); 

}
   
function draw() {

	background(175, g, b); // randomization of background

	if (mouseIsPressed){ 
		//when new ripple is created
		var newRip = makeRipple(mouseX, mouseY); 
		//ripple based on mouse position
		ripples.push(newRip); 
		b = random(200, 250); 
		g = random(200, 240); 
		//background color changes based on mouse color
	}
   	
   	for(var i = 0; i < ripples.length; i++){
   		//for the length of the array draw each of the ripples 
   		var r = ripples[i]; 
   		r.display(); 
   		//display the ripple
   	} 
   	if(ripples.length > 35){ 
   	// makes it so that when ripples are displayed, they will be removed from array 
   		ripples.shift();
   		ripples.shift();
   		ripples.shift();
   		ripples.shift();//removes 4 ripples  
   	}

}

//making the ripples objects 
function makeRipple(rX, rY){
	var ripple = { x: rX, 
				y: rY,
				diam: 0, 
				out: 0,  
				fade: 0, 
				colorR: generateRandom(0, 75), 
				colorG: generateRandom(100, 200), 
				colorB: generateRandom(50, 200), //color stays in blue range
				display: drawRipple}; 

	return ripple; 
}

function drawRipple(){ // how to display ripple 

	for (var i = 0; i < 5; i++){
		 this.diam = this.out - 25 * i; // makes circle size increase

		if(this.diam > 0){ 
			// fading out fill and stroke 
			this.fade = map(this.diam, 0, 300, 255, 100); 
			//mapping the fill to part of the canvas, so it fades in a certain time 
			push(); 
			strokeWeight(1); 
			//stroke will be background color 
			stroke(175, g, b, this.fade);  
			fill(this.colorR, this.colorG, this.colorB, this.fade);
			//fill is based on the color of the ripple object  
			ellipse(this.x, this.y, this.diam); 
			//multiple ripples made from the ellipse 
			pop(); 
		}

	}
	// when more ripples in the array/screen, more waves and speed 
	if(ripples.length > 25){ 
		this.out += 4; // amount ripple changes 
	}
	else {
		this.out += 2; //slower speed of ripples 
	}
	 
	
}

function generateRandom(x, y){
	var r = floor(random(x, y)); 
	//creates random variable + returns it 
	return r;
}


For my final project, I created a program that creates and animates ripples based on where your mouse touches. The color of the ripples changes randomly but stays in the blue range. The background color also changes randomly. The ripples fade using the map function, and if there are more ripples on the water, they move together faster.

Chelsea Fan & Katrina Hu – Final Project

Final copy

/* Chelsea Fan and Katrina Hu
Section 1B and Section 1C
chelseaf@andrew.cmu.edu and kfh@andrew.cmu.edu
Project-15
*/

//important variables
var killCount = 0;
var score = 0;
var yCoord = 0;
var snow = [];
var bear = [];
var c1;
var c2;

function setup() {
    createCanvas(600, 480);
    frameRate(60);
    //initial collection of bears
    for (i = 0; i < 1; i++) {
        var bearY = -40;
        bear[i] = makeBear(bearY);
    }
    //setting color of background
    c1 = color(106, 197, 252);
    c2 = color(126, 127, 207);
    //initial collection of snows
    for (i = 0; i < 60; i++) {
        var snowx = random(width);
        var snowy = random(0, height);
        snow[i] = makeSnow(snowx, snowy);
    }
}

function draw() {
    setGradient(c1, c2);
///////// BY CHELSEA
    //draw Sun
    noStroke();
    fill(255, 252, 227, 120);
    ellipse(80, 250, 85, 85);
    fill(255, 246, 179, 140);
    ellipse(80, 250, 70, 70);
    fill(255, 238, 112, 200);
    ellipse(80, 250, 50, 50);
    //draw background
    drawMountains2();
    drawMountains();
    //bears
    updateBear();
    removeBearFromView();
    addBear();
    drawKill();
    //more scenery things
    drawWater();
    drawIce();
    snows();
    //end of game
    endGame();
}

///////// BY KATRINA
function drawKill() {
    //printing score and number of bears killed
    fill(255);
    textSize(20);
    textAlign(RIGHT);
    noStroke();
    text("Kill Count = " + killCount, width - 70, 50);
    text("Score = " + score, width - 70, 75);
}

///////// BY CHELSEA
function endGame() {
    //end screen if five bears killed 
    //and restart game button
    if(killCount == 5) {
        textSize(50);
        fill(255);
        textAlign(CENTER);
        text("GAME OVER", width/2, height/2-100);
        for (var i = 0; i < bear.length; i++) {
            bear[i].speed = 0;
        }
        textSize(25);
        fill(255, 150);
        noStroke();
        rect(width/2 - 80, height/2 - 40, 160, 60);
        fill(50);
        text("RESTART", width/2, height/2);
    }
}

///////// BY KATRINA
function mouseClicked() {
    //if restart button clicked, reset game 
    if(killCount == 5) {
        if (mouseX > 220 & mouseX < 380 && mouseY > 200 && mouseY < 260) {
            bear = [];
            killCount = 0;
            score = 0;
            for (var i = 0; i < bear.length; i++) {
                bear[i].speed = 2;
            }
        }
    }
}

///////// BY KATRINA
function setGradient(c1, c2) {
    //gradient color sky background
    noFill();
    for (var y = 0; y < height; y++) {
        var inter = map(y, 0, height, 0, 1);
        var c = lerpColor(c1, c2, inter);
        stroke(c);
        line(0, y, width, y);
    }
}

///////// BY CHELSEA
function drawWater() {
    //water color and transparency
    fill(0, 107, 214, 100);
    noStroke();
    //water level 
    rect(0, height - (96 * killCount) - 20, width, height + 30)
}

///////// BY KATRINA
function drawIce() {
    fill(245, 68, 59);
    rect(mouseX + 8, height - (96 * killCount) - 100, 55, 30); //sign
    textSize(10);
    textFont('Georgia');
    fill(255);
    rect(mouseX + 8, height - (96 * killCount) - 100, 8, 75); //pole
    text('NORTH', mouseX + 55, height - (96 * killCount) - 90); //words
    text('POLE', mouseX + 50, height - (96 * killCount) - 75);
    fill(162, 232, 250)
    rect(mouseX, height - (96 * killCount) - 15, 100, 4); //ice
    fill(255);
    rect(mouseX, height - (96 * killCount) - 25, 100, 10); //ice
    fill(245, 68, 59);
    for(lines = 0; lines < 4; lines++) { //stripes
        rect(mouseX + 8, height - (96 * killCount) - lines * 20 - 33, 8, 7);
    }
    fill(255, 242, 145);
    ellipse(mouseX + 12, height - (96 * killCount) - 106, 15, 15) //top of pole
}

///////// BY CHELSEA
function drawSnow() {
    noStroke();
    fill(255, 255, 255, 170); ///snow color and transparency
    push();
    translate(this.x2, this.y2); //draw snow at x2, y2
    ellipse(10, 10, 5, 5); //snow shape
    pop();
}

///////// BY CHELSEA
function makeSnow(xlocation, ylocation) {
    //snow object
    var makeS = {x2: xlocation, 
                y2: ylocation, 
                snowx: random(0, width), 
                snowy: 0,
                speed: random(1, 2),
                move: moveSnow,
                draw: drawSnow}
    return makeS;
}

///////// BY CHELSEA
function moveSnow() {
    this.y2 += this.speed; //speed of snow moving
    if (this.y2 >= height - (96 * killCount) - 30) { //restart snow on top
        this.y2 -= height;
    }
}

///////// BY CHELSEA
function snows() {
    //move and draw all individual snows
    for(i = 0; i < snow.length; i++) {
        snow[i].move();
        snow[i].draw();
    }
}

///////// BY CHELSEA
function drawMountains(){
    noStroke();
    fill(192, 200, 207); //mountain color
    beginShape(); 
    for (i = 0; i < width; i++) {
        var mountainSpeed = .0005; //speed of mountains moving
        var mountainDetail = 0.009; //smoothness of mountains
        var t = (i * mountainDetail) + (millis() * mountainSpeed);
        //mountain y coord
        var y = map(noise(t), 0, 1.2, height/2, height);
        //keep drawing mountain
        vertex(i, y);
    }
    //height constriant of mountains
    vertex(width, height);
    //restart mountains at left side 
    vertex(0, height);
    endShape();
}

///////// BY CHELSEA
function drawMountains2(){
    noStroke();
    fill(245); //mountain color
    beginShape(); 
    for (i = 0; i < width; i++) {
        var mountainSpeed = .0003; //speed of mountains moving
        var mountainDetail = 0.007; //smoothness of mountains
        var t = (i * mountainDetail) + (millis() * mountainSpeed);
        //mountain y coord
        var y = map(noise(t), 0, 2, height/2, height);
        //keep drawing mountain
        vertex(i, y);
    }
    //height constriant of mountains
    vertex(width, height);
    //restart mountains at left side 
    vertex(0, height);
    endShape();
}

///////// BY KATRINA
function updateBear() {
    //move and draw all individual bears
    for (var i = 0; i < bear.length; i++) {
        bear[i].move();
        bear[i].display();
    }
}

///////// BY KATRINA
function removeBearFromView() {
    //if bear lands on ice, delete bear
    for(var i = 0; i < bear.length; i++) {
        if (bear[i].x > mouseX & bear[i].x < mouseX + 100 && (bear[i].y > height - (96 * killCount) - 50 && bear[i].y < height - (96 * killCount) - 40)) {
            bear.splice(i, 1);
            score += 1;
        }
        //if bear leaves screen, remove from array
        else if (bear[i].y > height + 40) {
            bear.splice(i, 1);
            killCount += 1;
        }
    }
}

///////// BY KATRINA
function makeBear(startY) {
    //bear object
    var myBear = {x: random(30, 570),
                y: startY,
                speed: 2,        
                move: bearMove,
                display: bearDisplay}
    return myBear;
}

///////// BY KATRINA
function bearMove() {
    //to move bear
    this.y += this.speed;
}

///////// BY KATRINA
function bearDisplay() {
    //drawing bear shape
    noStroke();
    fill(255);
    ellipse(this.x, this.y, 43, 60); //body
    ellipse(this.x + 14, this.y + 25, 12, 20); //right leg
    ellipse(this.x - 14, this.y + 25, 12, 20); //left leg
    ellipse(this.x, this.y - 30, 27, 32); //head
    ellipse(this.x + 9, this.y - 42, 8, 8); //right ear
    ellipse(this.x - 9, this.y - 42, 8, 8); //left ear
    fill(240);
    ellipse(this.x, this.y, 30, 36); //body
    fill(210);
    ellipse(this.x + 9, this.y - 42, 5, 5); //right inner ear
    ellipse(this.x - 9, this.y - 42, 5, 5); //left inner ear
    ellipse(this.x, this.y - 31, 9, 9); //snout
    fill(0);
    ellipse(this.x + 5, this.y - 37, 4, 4); //right eye
    ellipse(this.x - 5, this.y - 37, 4, 4); //left eye
    ellipse(this.x, this.y - 32, 6, 3); //nose
    fill(255);
    ellipse(this.x + 5.5, this.y - 35.5, 2, 2); //right inner eye
    ellipse(this.x - 5.5, this.y - 35.5, 2, 2); //left inner eye
    stroke(0);
    line(this.x, this.y - 32, this.x1, this.y - 29) //line from nose
}

///////// BY KATRINA
function addBear() {
    //add new bears to array with small probability
    var newBearProb = 0.005;
    if(random(0,1) < newBearProb) {
        bear.push(makeBear(-40));
    }
}

Instructions: Move the ice block with mouse to catch the falling bears. If you miss the bears, they will drown and the water level rises. If you miss 5 bears, the game ends. Press Restart to play again!

This was a fun project to make. Collaborating together was very helpful as we could learn from each other’s mistakes. However, it is difficult to code on two computers. We really enjoyed this experience and hope you enjoy the game!

YouieCho-FinalProject

I created an interactive clock that includes two modes that the user can switch between: normal, and Christmas. Each of the two modes draws a green tree and a snowy Christmas tree. In the beginning, the user wouldn’t know what the wiggly lines are drawing, but as they wait, the tree images begin to appear. The drawing refreshes when they switch between the two modes.

The time is displayed quantitatively as numbers and more visually with bars on the tree trunk, and mouse movement creates variant colors for certain features.

sketch

/* Youie Cho
   Section E
   minyounc@andrew.cmu.edu
   Final-Project*/

// Set up turtles to draw paths. Two draw their own paths simultaneously.
var ttl;
var ttl2;
var currIter = 0;

// Sets color for tree, outside area, text, and background
var rTree = 0;
var gTree = 100;
var bTree = 0;
var rOutside = 64;
var gOutside = 147;
var bOutside = 255;
var rText = 255;
var gText = 255;
var bText = 255;
var backgroundCol = 255;

// Ball colors (Christmas mode)
var ballcolors = ["red", "green", "pink", "orange", 'rgb(18, 89, 52)',
                'rgb(140, 0, 0)', 'rgb(252, 186, 3)', 'rgb(217, 86, 30)'];

// Coordinates and opacity for drawing star at top (Christmas mode)
var x = [300, 311, 333, 319, 321, 300, 279, 281, 267, 289];
var y = [48, 67, 73, 90, 112, 103, 112, 90, 73, 67];

// Opacity for star (Christmas mode)
var opacity = 0;

function setup() {
    createCanvas(600, 600);
    background("white");

    // Create turtles
    ttl = makeTurtle(0, 300);
    ttl.setWeight(1);
    ttl2 = makeTurtle(600, 300);
    ttl2.setWeight(1);
}

function draw() {
    time(); // Displays time witn numbers
    trunk(); // Trunk displays time with bars
    star(); // Star displays in Christmas mode
    ttl1Mvt(); // ttl1 settings
    ttl2Mvt(); // ttl2 settings

    // Turtle movement per frame
    currIter ++;
    ttl.forward(10);
    ttl.right(random(-50, 50));
    ttl2.forward(10);
    ttl2.left(random(-50, 50));

    buttons(); // Buttons used to switch between modes
}

function time() {
    // Text box
    noStroke();
    fill(rTree, gTree, bTree);
    rectMode(CENTER);
    rect(width / 2, 293, 140, 32);

    // Display hours with AM/PM mode, minutes, and seconds
    noStroke();
    fill(rText, gText, bText);
    if (hour() > 12) {
        textSize(20);
        text(hour() - 12, 245, 300);
        textSize(10);
        text("PM", 345, 300);
    } else {
        textSize(20);
        text(hour(), 245, 300);
        textSize(10);
        text("AM", 345, 300);
    }
    textSize(20);
    text(minute(), 280, 300);
    text(second(), 315, 300);
}

function trunk() {
    rectMode(CORNER);
    strokeWeight(0.5);
    stroke(128, 70, 13);
    fill(backgroundCol, backgroundCol, backgroundCol);
    rect(259.5, 370, 81, 120);
    fill(128, 70, 13);

    // Progression of brown bars display time
    var prgH = map(hour(), 0, 23, 0, 120);
    rect(259.5, 370, 25, prgH);
    var prgM = map(minute(), 0, 59, 0, 120);
    rect(287.5, 370, 25, prgM);
    var prgS = map(second(), 0, 59, 0, 120);
    rect(315.5, 370, 25, prgS);
}

function star() {
    var nPoints = x.length;
    noStroke();

    // Star color changes according to mouseX
    var starCol = map(mouseX, 0, width, 130, 220);
    fill(255, starCol, 100, opacity);
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        vertex(x[i], y[i]);
    }
    endShape(CLOSE);
    noStroke();
}

function ttl1Mvt() {
    // Turtle does not go outside of the canvas
    if (ttl.x >= width || ttl.x <= 0 || ttl.y >= height || ttl.y <= 0) {
        ttl.penUp();
        ttl.goto(300, 300);
        ttl.penDown();
    }

    // Color settings for tree area and outside area
    if ((ttl.x > 280 & ttl.x < 320 && ttl.y > 90 && ttl.y < 110) ||
        (ttl.x > 260 && ttl.x < 340 && ttl.y > 110 && ttl.y < 150) ||
        (ttl.x > 240 && ttl.x < 360 && ttl.y > 150 && ttl.y < 200) ||
        (ttl.x > 200 && ttl.x < 400 && ttl.y > 200 && ttl.y < 260) ||
        (ttl.x > 150 && ttl.x < 450 && ttl.y > 260 && ttl.y < 370)) {
        ttl.setColor(color(rTree, gTree, bTree));
    } else {
        ttl.setColor(color(rOutside, gOutside, bOutside));
    }
}

function ttl2Mvt() {
    // Turtle does not go outside of the canvas
    if (ttl2.x >= width || ttl2.x <= 0 || ttl2.y >= height || ttl.y <= 0) {
        ttl2.penUp();
        ttl2.goto(300, 300);
        ttl2.penDown();
    }

    // Color settings for tree area and outside area
    if ((ttl2.x > 280 & ttl2.x < 320 && ttl2.y > 90 && ttl2.y < 110) ||
        (ttl2.x > 260 && ttl2.x < 340 && ttl2.y > 110 && ttl2.y < 150) ||
        (ttl2.x > 240 && ttl2.x < 360 && ttl2.y > 150 && ttl2.y < 200) ||
        (ttl2.x > 200 && ttl2.x < 400 && ttl2.y > 200 && ttl2.y < 260) ||
        (ttl2.x > 150 && ttl2.x < 450 && ttl2.y > 260 && ttl2.y < 370)) {
        ttl2.setColor(color(rTree, gTree, bTree));
    } else {
        ttl2.setColor(color(rOutside, gOutside, bOutside));
    }
}

function buttons() {
    noStroke();
    fill(mouseY / 5 + 200, mouseX / 5 + 200, mouseX / 5 + 100);
    rect(13, 558, 100, 33);
    rect(487, 558, 100, 33);
    strokeWeight(0.5);
    fill(rOutside, gOutside, bOutside);
    textSize(15);
    text("Normal", 40, 580);
    text("Christmas", 505, 580);
}

function mousePressed() {
    // NORMAL MODE ////////////////////////////////////////////////////////////
    if (mouseX >= 13 & mouseX <= 113 && mouseY >= 558 && mouseY <= 691) {
        // Turtle drawing refreshes upon cliking the button
        noStroke();
        clear();
        backgroundCol = 255;
        background(backgroundCol, backgroundCol, backgroundCol);
        opacity = 0;

        // Color settings
        rTree = 0; // Green tree
        gTree = 100;
        bTree = 0;
        rOutside = 64; // Blue outside
        gOutside = 147;
        bOutside = 255;
        rText = 240; // Light green text
        gText = 247;
        bText = 218;
    }

    // CHRISTMAS MODE /////////////////////////////////////////////////////////
    if (mouseX >= 487 & mouseX <= 587 && mouseY >= 558 && mouseY <= 691) {
        // Turtle drawing refreshes upon cliking the button
        clear();
        backgroundCol = 0;
        background(backgroundCol, backgroundCol, backgroundCol);
        opacity = 100; // Displays star only in Christmas mode

        // Color settings
        rTree = 255; // White tree
        gTree = 255;
        bTree = 255;
        rOutside = 255; // Yellow outside
        gOutside = 213;
        bOutside = 28;
        rText = 248; // Dark yellow text
        gText = 178;
        bText = 41;

        // Ornaments (Christmas mode)
        noStroke();
        for (var i = 0; i < ballcolors.length; i++) {
            for (var j = 0; j < ballcolors.length; j++) {
            fill(ballcolors[i]);
            }
        ellipse(random(280, 320), random(150, 250), 12, 12);
        ellipse(random(170, 450), random(250, 370), 18, 18);
        }
    }
}

// TURTLE FUNCTIONS ///////////////////////////////////////////////////////////
function turtleLeft(d) {
    this.angle -= d;
}

function turtleRight(d) {
    this.angle += d;
}

function turtleForward(p) {
    var rad = radians(this.angle);
    var newx = this.x + cos(rad) * p;
    var newy = this.y + sin(rad) * p;
    this.goto(newx, newy);
}

function turtlePenDown() {
    this.penIsDown = true;
}

function turtlePenUp() {
    this.penIsDown = false;
}

function turtleGoTo(x, y) {
    if (this.penIsDown) {
      stroke(this.color);
      strokeWeight(this.weight);
      line(this.x, this.y, x, y);
    }
    this.x = x;
    this.y = y;
}

function turtleSetColor(c) {
    this.color = c;
}

function turtleSetWeight(w) {
    this.weight = w;
}

function makeTurtle(tx, ty) {
    var turtle = {x: tx, y: ty,
                  angle: 0.0,
                  penIsDown: true,
                  color: color(128),
                  weight: 1,
                  left: turtleLeft, right: turtleRight,
                  forward: turtleForward,
                  penDown: turtlePenDown, penUp: turtlePenUp,
                  goto: turtleGoTo,
                  setColor: turtleSetColor, setWeight: turtleSetWeight,
                 };
    return turtle;
}

Christmas mode / short time elapsed
Christmas mode / long time elapsed
Normal mode

Sammie Kim – Final Project – 12

For this project, I wanted to create a recycling game that educates all age levels upon proper recycling, which is one of the basic ways that we can all contribute to protect our environment. Through the process, I learned a lot, especially how there are a lot of trash items that are not recyclable—this emphasized the importance of reusing items and reducing waste in general. The user can simply explore the environment, drag any waste item and drop it in any of the waste bins below. If the waste is thrown in the wrong bin, information will automatically show up on the top to guide the user, while also giving extra tips for reducing such trash. 

sketch

//Sammie Kim
//Section D
//sammiek@andrew.cmu.edu
//Final Project

//Global Variables
var FOOD = 0; //Index number within the waste bin type array
var PLASTIC = 1;
var PAPER = 2;
var TRASH = 3;
var score = 0;
var styrofoamBox = createStyrofoamBox();
var tissue = createTissue();
var hanger = createHanger();
var newspaper = createNewspaper();
var pizzaBox = createPizzaBox();
var plasticBag = createPlasticBag();
var plasticBottle = createPlasticBottle();
var paperBag = createPaperBag();
var appleCore = createApple();
var coffeeCup = createCoffee();
var fishbones = createFishbones();
var toothpaste = createToothpaste();
var mirror = createMirror();
var bubblewrap = createBubbleWrap();
var foodBin = createFoodBin();
var plasticBin = createPlasticBin();
var paperBin = createPaperBin();
var trashBin = createTrashBin();
var wastes = [styrofoamBox, tissue, hanger, newspaper, pizzaBox, plasticBag,
              plasticBottle, paperBag, appleCore, coffeeCup, fishbones,
              toothpaste, mirror, bubblewrap];
var wasteBins = [foodBin, plasticBin, paperBin, trashBin];
//Boolean Variables
var correct = false;
var selected = false;

//Use objects to create different wastes and wastebins with specific traits
function createStyrofoamBox() {
    var styrofoamBox = {
        url: "https://i.imgur.com/Lb1P88W.png",
        initX: 78,
        initY: 102,
        x: 78,
        y: 102,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: TRASH,
        note: "Styrofoam is a non-recyclable material because it contains "
              + "polysteryene, which is non-biodegradable."
        }
    return styrofoamBox;
}

function createTissue() {
    var tissue = {
        url: "https://i.imgur.com/s6rZAJu.png",
        initX: 145,
        initY: 95,
        x: 145,
        y: 95,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: TRASH,
        note: "Dirty tissues should be thrown in trash."
        }
    return tissue;
}

function createHanger() {
    var hanger = {
        url: "https://i.imgur.com/dE1sDsn.png",
        initX: 253,
        initY: 163,
        x: 253,
        y: 163,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: TRASH,
        note: "Plastic hangers are not purely plastic, and their curved ends "
              + "can be problematic in recycling equipment. "
        }
    return hanger;
}

function createNewspaper() {
    var newspaper = {
        url: "https://i.imgur.com/FkD5sJK.png",
        initX: 0,
        initY: 253,
        x: 0,
        y: 253,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: PAPER,
        note: "Newspapers should be recycled in paperbin."
        }
    return newspaper;
}

function createPizzaBox() {
    var pizzaBox = {
        url: "https://i.imgur.com/ZRjCbEW.png",
        initX: 172,
        initY: 102,
        x: 172,
        y: 102,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: TRASH,
        note: "Pizzabox cannot be recycled due to its wet and greasy cardboard "
              + "that cannot be processed in recycling equipment. "
              + "It can also attract insects and rodents."
        }
    return pizzaBox;
}

function createPlasticBag() {
    var platicBag = {
        url: "https://i.imgur.com/PDtsB6D.png",
        initX: 94,
        initY: 172,
        x: 94,
        y: 172,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: PLASTIC,
        note: "Most recycling facilities can only handle rigid materials that can "
              + "be separated, so plastic bags and wraps are generally not accepted. "
              + "But we can always reuse them for collecting trash."
        }
    return platicBag;
}

function createPlasticBottle() {
    var plasticBottle = {
        url: "https://i.imgur.com/6OEa9bA.png",
        initX: 393,
        initY: 95,
        x: 393,
        y: 95,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: PLASTIC,
        note: "Empty plastic bottles belong in the plastic bin. "
        + "The better option is to carry reusable waterbottles."
        }
    return plasticBottle;
}

function createPaperBag() {
    var paperBag = {
        url: "https://i.imgur.com/QsPO9ph.png",
        initX: 364,
        initY: 153,
        x: 364,
        y: 153,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: PAPER,
        note: "Clean paper bags belong in the paper bin. Still, the best "
        + "option would be to reuse them."
        }
    return paperBag;
}

function createApple() {
    var appleCore = {
        url: "https://i.imgur.com/QX98sKU.png",
        initX: 274,
        initY: 258,
        x: 274,
        y: 258,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: FOOD,
        note: "Any type of leftover food belong in the organic waste bin."
        }
    return appleCore;
}

function createCoffee() {
    var coffeeCup = {
        url: "https://i.imgur.com/sys0QnS.png",
        initX: 351,
        initY: 87,
        x: 351,
        y: 87,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: TRASH,
        note: "Unlike most paper items, paper cups are usually coated in platic "
              + "to hold liquid to prevent leaking. "
              + "Although many cafes are beginning to use compostable cups, "
              + "the best option is carrying coffee mugs or reusable bottles."
        }
    return coffeeCup;
}

function createFishbones() {
    var fishbones = {
        url: "https://i.imgur.com/wju8gLe.png",
        initX: 205,
        initY: 264,
        x: 205,
        y: 264,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: FOOD,
        note: "Any type of leftover food belong in the organic waste bin."
        }
    return fishbones;
}

function createToothpaste() {
    var toothpaste = {
        url: "https://i.imgur.com/na3BnTw.png",
        initX: 104,
        initY: 260,
        x: 104,
        y: 260,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: PLASTIC,
        note: "Toothpaste tubes should be properly cleaned out before "
              + "being placed in the plastic recycling bin."
        }
    return toothpaste;
}

function createMirror() {
    var mirror = {
        url: "https://i.imgur.com/NAh1S2x.png",
        initX: 142,
        initY: 130,
        x: 142,
        y: 130,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: TRASH,
        note: "Mirrors cannot be recycled due to the coating used on glass "
              + "to make it reflective. Be sure to wrap broken mirror pieces "
              + "before throwing them in the garbage."
        }
    return mirror;
}

function createBubbleWrap() {
    var bubblewrap = {
        url: "https://i.imgur.com/cvJ1Iou.png",
        initX: 336,
        initY: 245,
        x: 336,
        y: 245,
        selected: false,
        stay: true,
        dragging: false,
        informing: false,
        type: TRASH,
        note: "Although many plastics are recylable, bubble wraps and bags "
              + "cannot be recyled due to their thin films that can get tangled "
              + "in recycling machines."
        }
    return bubblewrap;
}

function createPaperBin() {
    var paperBin = {
        url: "https://i.imgur.com/AgJIG61.png",
        x: 229,
        y: 342,
      }
    return paperBin;
}

function createPlasticBin() {
    var plasticBin = {
        url: "https://i.imgur.com/6x6FPJW.png",
        x: 117,
        y: 342,
    }
    return plasticBin;
}

function createFoodBin() {
    var foodBin = {
        url: "https://i.imgur.com/sSve89v.png",
        x: 8,
        y: 342,
    }
    return foodBin;
}

function createTrashBin() {
    var trashBin = {
        url: "https://i.imgur.com/jm4NMB8.png",
        x: 343,
        y: 342,
    }
    return trashBin;
}

function setup() {
    createCanvas(450, 480);
}

function draw() {
    //load images for background, wastes, and waste bins
    background(220);
    image(backgroundPic, 0, 0);
    for (var i = 0; i < wasteBins.length; i++) {
        image(wasteBinsPics[i], wasteBins[i].x, wasteBins[i].y);
    }
    //Show explanation on top of the canvas if informing is true
    for (var i = 0; i < wastes.length; i++) {
        if (wastes[i].informing) {
            fill(220);
            noStroke();
            rect(0, 0, 450, 60);
            fill(0);
            text(wastes[i].note, 10, 10, 440, 480);//wrapping text within canvas
        }
        if (wastes[i].stay) { //if stay is true, images are all shown on canvas
            image(wastePics[i], wastes[i].x, wastes[i].y);
            if (wastes[i].dragging) {
                //update waste with current mouse locations
                wastes[i].x = mouseX - wastePics[i].width / 2;//offset amount
                wastes[i].y = mouseY - wastePics[i].height / 2;
        }
      }
    }
    if (correct) {
        text("Correct!", 10, 20); //shows up when answer is correct
    }
    fill(255);
    text("Score: " + score, 10, 90); //show scoreboard
}

function preload() {
    //Preload all the images by pushing the objects' URL into new array
    var backgroundURL = "https://i.imgur.com/4jWCbcI.png"
    backgroundPic = loadImage(backgroundURL);
    wastePics = [];
    for (var i = 0; i < wastes.length; i++) {
        wastePics.push(loadImage(wastes[i].url));
    }
    wasteBinsPics = []
    for (var i = 0; i < wasteBins.length; i++) {
        wasteBinsPics.push(loadImage(wasteBins[i].url));
    }
}

function mousePressed() {
    //Use mousePressed to drag each trash item within the canvas
    //I created parameters for each trash image, so that the mouse can click
    //within the area of each trash image.
    for (var i = 0; i < wastes.length; i++) {
        wastes[i].informing = false; //Clear information when mouse is pressed.
        var x0 = wastes[i].x; //top left X coordinate
        var y0 = wastes[i].y; //top right Y coordinate
        var x1 = wastes[i].x + wastePics[i].width; //top right X coordinate
        var y1 = wastes[i].y + wastePics[i].height; //bottom y coordinate
        if (!selected & x0 < mouseX && mouseX < x1 && y0 < mouseY && mouseY < y1) {
            selected = true; //trash is selected within the image boundaries
            wastes[i].dragging = true;
        }
    }
}

function mouseReleased() {
    //Use mouseReleased to evaluate whether the chosen trash is
    //dropped into the correct bin.
    //Like previously, I created specific parameters for trashbin images.
    selected = false;
    for (var i = 0; i < wastes.length; i++) {
        if (wastes[i].dragging) {
            wastes[i].dragging = false;
            var corrBin = wasteBins[wastes[i].type];
            var corrBinPic = wasteBinsPics[wastes[i].type];
            var x0 = corrBin.x;
            var y0 = corrBin.y;
            var x1 = corrBin.x + corrBinPic.width;
            var y1 = corrBin.y + corrBinPic.height;
            if (y0 < mouseY & mouseY < y1) {
                //Since all trashbins have the same Y height, I differentiated
                //the correct bin by determining the X locations
                if (x0 < mouseX && mouseX < x1) { //Correct Bin
                    correct = true;
                    wastes[i].stay = false; //waste will disappear
                    wastes[i].informing = false; //information will not show
                    score += 1; //score is updated by one when answer is correct
                } else {
                    //if incorrect, information will show up, and
                    //the waste image will go back to its initial location
                    correct = false;
                    wastes[i].informing = true;
                    wastes[i].x = wastes[i].initX; //initial X coordinate
                    wastes[i].y = wastes[i].initY; //initial Y coordinate
                }
            } else {
                correct = false; //the default status
            }
        }
    }
}

Joseph Zhang – Final Project -12

sketch

// Joseph Zhang
// 15-104 Final Project
// Section E

var rectangles = [];
var gutter = 30;
var totalRows = 15;
var totalCols = 15;
var centerCol = totalCols / 2;
var centerRow = totalRows / 2;
var rectH = 70;

function setup() {
    createCanvas(450, 450, WEBGL);
    // PUT RECTANGLES INTO ARRAY
    for( x = 0; x < totalRows; x++) {
        for ( y = 0; y < totalCols; y++) {
            rectangles.push(createCube(x * gutter, y * gutter, x, y));
        }
    }
}

var bgColor;
var bg = 0;

function draw() {

    rotateY(map(mouseX, 0, height, -.15, .15));
    rotateX(map(mouseY, 0, height, .15, -.15));
    translate(map(mouseX / 10 , 0, width / 10, -10, 10), map(mouseY / 10 , 0, height / 10, -10, 10), 0);

    //INTERACTIVE CONTROLS - UP AND DOWN
    if( keyIsPressed &  keyCode === LEFT_ARROW) {
        if( rectH > -200) {
            rectH -= 3;
            print(rectH);
        }
    }

    else if( keyIsPressed &  keyCode === RIGHT_ARROW) {
        if( rectH < 100) {
            rectH += 3;
            print(rectH);
        }
    }

    // COLOR BACKGROUND
    if(bgColor) {
        if ( bg > 0) {
            bg -= 20;
        }
    }

    else{
        if( bg < 255) {
            bg += 20;
        }
    }
    background(bg);

    rectMode(CENTER);  
    rotateX(radians(40));
    translate( - width / 2, - height / 2 + 15, 0);

    // REPEATEDLY DRAW EVERY PRISM IN DRAW
    for( i = 0; i < rectangles.length; i++) {
        rectangles[i].drawRect();
        rectangles[i].raiseRect();
    }
}

// CUBE OBJECT
function createCube(row, col, r, c) {
    var rectObj = {
        w: 19,
        xPos: row,
        yPos: col,
        offset: dist(r, c, centerCol, centerRow),
        currentHeight: this.offset,
        // UPDATES THE HEIGHT OF RECTANGLE
        drawRect: function() {
            if (this.currentHeight > 0) {
                fill(map(this.currentHeight, 10, 70, 0, 255));
            }
            else{
                fill(map(this.currentHeight, 10, 70, 0, -255));
            }

            push();
            translate(this.xPos, this.yPos , this.currentHeight);
            box(this.w, this.w, this.currentHeight);
            pop();
        },
        // CHANGES THE HEIGHT THROUGH MAPPING CANVAS
        raiseRect: function() {
            this.currentHeight = map( sin(this.offset), -1, 1, 10, rectH);
            this.offset += .1;
        }  
    }
    return rectObj;
}

// IF ENTER KEY IS PRESSED, CHANGE BACKGROUND
function keyPressed() {
        if( keyCode === ENTER) {
            bgColor = !bgColor;
        }
}

INTERACTIVE CONTROLS (click on canvas first):

LEFT ARROW: Decrease wave amplitude

RIGHT ARROW: Decrease wave amplitude

ENTER: Change background color

***IF LAGGING, VISIT https://editor.p5js.org/jxsephz/sketches/9Dqxil-1P

————————

For this project, I wanted to experiment with manipulating forms in three dimensional space. As someone who loves mathematical patterns, I explored ways that I could utilize the oscillation of a Sine wave.

Jamie Park – Final Project

My project was inspired by single-line drawings and line-drawing tools, like etch a sketch. I always had a desire to draw something only using one line, but I did not have the talent to do so. I also never had the patience to draw using etch a sketch. Therefore, I created a p5js drawing tool that allows you to create single-line drawings. In order to draw, use the arrow keys. You can change the color of the line by pressing on the space bar (the circle on the bottom will indicate the current color status), change the line weight by clicking on the arrows (numbers indicate the line weight), and clear canvas by clicking on the “clear” button. I hope you have fun as much as I had while I was coding for this project!

Plus, try drawing a diagonal line by pressing onto two arrow keys at the same time! 🙂

sketch

/* Jamie Park (jiminp)             Section E
   15 - 104                     Final Project */

var ttl; //global variable for the turtle
var colors = ["Coral", "DarkTurquoise", "DarkGrey", "blue",
"FireBrick", "Gold", "Lavender", "LightPink", "PowderBlue"]; //global variable for color values
var col = 0; //color index value
var strokeThickness = 2; //strokethickness as global value
var bgCol = 255;

function preload(){
    //preload image into the canvas
    var overlayURL = "https://i.imgur.com/5dpuHCX.png";
    overlay = loadImage(overlayURL);
}

function setup(){
    //creates a canvas
    createCanvas(500, 400);
    //sets the background color on white
    background(250);
    //makes the turtle at random parts of the canvas
    ttl = makeTurtle(random(150, 300), random(100, 300));
    ttl.setWeight(strokeThickness);
    ttl.setColor("coral");
}

function draw(){
    //display the image on the canvas
    image(overlay, 0, 0, 500, 400);
    //allows the user to draw the lines
    drawLines();
    //allows the user to change the color of lines
    displayStrokeWeight();
    drawTriangleButtons();
    displayCurrentColor();
    clearButton();
    boundTurtle();

}

function mousePressed(){
    //redraw when clicked on clear button
    clearCanvas();
    //when tou click the buttons, the thickness of the turtle stroke changes
    changeThickness();
}

function boundTurtle(){
    //set up local variables that wound bound the turtles
    var boundaries = 28;
    var bottomBoundaries = 58;

    //if turtle x is smaller than a set number, the turtle is the set number
    //set number due to the frame around the canvas
    if(ttl.x < boundaries){
        ttl.x = boundaries;
    }
    //if turtle y is smaller than a set number...
    if(ttl.y < boundaries + 2){
        ttl.y = boundaries + 2;
    }
    //if turtle x is greater than the set number...
    if(ttl.x > width - boundaries - 5){
        ttl.x = width - boundaries - 5;
    }
    //if turtle y is greater than the set number...
    if(ttl.y > height - bottomBoundaries){
        ttl.y = height - bottomBoundaries;
    }
}

function keyPressed(){
    //when spacebar is pressed, the color of the turtle changes
    //you can "find" your desired color by pressing on the space bar multiple times
    changeColor();
}

function changeColor(){
    if(keyCode === 32){
        //keyCode 32 is the space bar
        col = (col + 1) % colors.length;
        //you change the color by adding one into the color index above
        ttl.setColor(colors[col]);
    }
}

function drawLines(){
    //function that draws the lines when key is pressed accordingly
    //local variable that goes forward by 1.5 pixels every time key is pressed
    var distDraw = 1.5;
        //draws the line leftwards
    if(keyIsDown(LEFT_ARROW)){
        ttl.face(180);
        ttl.forward(distDraw);
    }
        //draws the line rightwards
    if(keyIsDown(RIGHT_ARROW)){
        ttl.face(0);
        ttl.forward(distDraw);
    }
        //draws an upward line
    if(keyIsDown(UP_ARROW)){
        ttl.face(270);
        ttl.forward(distDraw);
    }
        //draws a downward line
    if(keyIsDown(DOWN_ARROW)){
        ttl.face(90);
        ttl.forward(distDraw);
    }
}

function changeThickness(){
    //thickness of the stroke increases / decreases when the button is clicked
    if(mouseX < 450 & mouseX > 430 && mouseY > 280 && mouseY < 300){
        strokeThickness = strokeThickness + 1;
        //strokeweight increases by 1
    }
        //when mouseisPressed within the range of the triangular buttons, reduce the stroke weight by 0.05
    if(mouseX < 450 & mouseX > 430 && mouseY > 310 && mouseY < 340){
        strokeThickness = strokeThickness - 1;
        //strokeweight decreases by 1
    }
    //constrains the thickness of the stroke in value between 1 and 13
    strokeThickness = constrain(strokeThickness, 1, 13);
    //implements the weight to the turtle
    ttl.setWeight(strokeThickness);
}

function drawTriangleButtons(){
    //draws the triangle buttons on the bottm right corner of the canvas
    noStroke();
    fill("LightSalmon");
    //local variables that set height and width of the triangle to avoid magic nunbers
    var triangleW = 430;
    var triangleH = 300;
    //top triangle that increases the thickness
    triangle(triangleW, triangleH, triangleW + 20, triangleH, triangleW + 10, triangleH - 20);
    //bottom triangle to reduce the thickness
    triangle(triangleW, triangleH + 10, triangleW + 20, triangleH + 10, triangleW + 10, triangleH + 30);
}

function clearButton(){
    //draws the "clear" button on the top left corner
    fill("orange");
    noStroke();
    ellipse(50, 50, 25, 25);
    fill("white");
    text("clear", 40, 53);
    //informative text
    fill("gray");
    text("press on arrow keys to draw & space bar to change color,", 73, 50);
    text("and click on the arrow to change stroke thickness", 73, 60);
}

function clearCanvas(){
    //if mouse is within the proximity of the clear button, the canvas is cleared
    if(mouseX > 37.5 & mouseX < 62.5 && mouseY > 37.5 && mouseY < 62.5){
        clear();
        background(255);
        //strokeThickness and color index restart
        strokeThickness = 2;
        col = 8;
    }
}

function displayCurrentColor(){
    //displays current turtle color in a circle
    fill(colors[col]);
    ellipse(width * .815, height * .8, 10, 10)
}

function displayStrokeWeight(){
    //displays the strokeweight
    noStroke();
    fill("white");
    rect(430, 300, 18, 10);
    textSize(10);
    fill("SlateGray")
    textFont("GillSans");
    text(strokeThickness, 435, 308.5);
}

//------------------------------turtle code--------------------------------
function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}

Emma N-M — Final Project


My project is a spirograph application. You can move the two radius sliders, and vary the line length to change the design the math equation will create (the radii must be different values for the DRAW button to work). There are three different math equations you can use to create different designs (spirograph, epitrochoid, or another cool equation). The square in the top right hand corner allows you to set the pen color when you click on the box. This will open up a color gradient. Click anywhere and the box in the bottom righthand will show you a preview of the color you clicked on. Once you are happy with your pen color, hit “ENTER”. This will take you back to the set up screen. Hit the DRAW button to watch your design be created. When watching your drawing, you may hit the back arrow button or press “LEFT ARROW” key to go back to the set up screen. That’s it! Enjoy being mesmerized by art created with math.

finalProject-ENM

/* Emma Nicklas-Morris
enicklas
Section B
Final Project
*/ 

// radius1 46, radius2 31, LL 30 -- cool design

// point to draw the lines for the design
var x1;
var y1;
var x2 = x1;
var y2 = y1;

// used in sprigraph equations
var scaleN = 2.8;
var i = 0; // counter
var r1 = 10;
var r2 = 11;
var p = 2; // length of line from center

// used in other cool math equation
var l = p / r1;
var k = r1 / r2;

// epitrochoid equation variables
var a;
var b;

// drawing button
var drawing = false;
var justClicked = false; 
// back button
var backB = 30;
var backBX = 21;

var buttons = [];
var buttonText = [];
var equationText = [];
var equationCount = 1; // counts times the equation button is clicked
var e; // index to get the right equation displayed

var r1x = 25; // x position of radius 1 slider
var ry = 50; // y position for slider
var r2x = 175; // x position of radius 2 slider
var r1Min = 25; // min x position for radius 1
var r1Max = 125; // max x position for radius 1 
var r2Min = 175; // min x position for radius 2
var r2Max = 275; // max x position for radius 2
var radMin = 10; // user min for radii
var rad2Max = 70; // user radius 2 max
var rad1Max = 100; // user radius 1 max
var llMin = 2; // user line length min
var llMax = 65; // user line length max
var px = 315; // x position of line length (p)
var pMin = 315; // min x position of line length (p)
var pMax = 415; // max x position of line length (p)
var dragging = false;
var sliderCol = 170;

// which radius slider is clicked
var rad1 = false; 
var rad2 = false;
var lineL = false;
var rd = 12; // ball slider diameter
var r1Num = 10; // radius1 number displayed to user
var r2Num = 10; // radius2 number displayed to user
var lineNum = 5; // line length number displayed to user
var r12;        // radius1 - radius2
var diffRadii = false; // can't have the same radii

var backCol = 240; // background color
var userCol = 100; // intializes pen color
var gradSection = 84; // max width of each gradient section
var choosing = false;

var radius2; // object text for radius 2
var lineLen; // object text for line length

// location for elements on the screen
var diffRadX = 150;
var diffRadY = 100;
var eqX = 20;
var eqY = 30;
var rad2X = 190;
var llX = 320;
var colorX = 445;
var colorY = 25;
var colorMid = 165;
var colorPink = 147;
var eqW = 120;


function setup() {
	createCanvas(500, 400);
	background(backCol);
	frameRate(40);

}

function draw() {
	// stroke(cos(i/10)*(255/2), 0, sin(i/20)*(255/2), i);
	
	// screen mode: draws the spirograph
	if ((drawing) & (diffRadii)) {

		// back button on draw screen
		drawBackButton();

		// hide all setting buttons when in draw mode
		if (justClicked) {
            fill(backCol);
            rect(0, 0, width, height);
            justClicked = false; 
		}
		
        x1 = width / 2;
        y1 = height / 2;

        // spirograph
        if (e === 0) {
            spirograph();
            
        }

        // Epitrochoid
        else if (e === 1) {
            epitrochoid();
        }

        // other cool math equation
        else if (e === 2) {
            other();
        }

	}

	// screen mode: set the settings
	else {
		noStroke();
		// new screen -- hides drawing
		fill(backCol);
		rect(0, 0, width, height);

        // draws the buttons
		makeAndDrawButtons();
        makeTextForButtons();
        drawText();
        displayEquation();
        
        // which slider user is dragging
        checkDragging();

        // draw choose color button
        chooseColor();

        // draw radius sliders
        radiusSliders();

        // draws the example circles for the math
        exampleCircles();

        // line length (p)
        drawLineLength();

        // can't draw using the same radii
        checkRadii();

        // choosing pen color
        choosePenColor();

		// reset equation variables
		x1 = width / 2;
		y1 = height / 2;
		x2 = undefined;
		y2 = undefined;
		i = 0;   

	}

    i += 0.1;

}

function checkDragging() {
    if (dragging) {
        if (rad1) {
            r1x = mouseX;
        }
        else if (rad2) {
            r2x = mouseX;
        }

        else if (lineL) {
            px = mouseX;
        }
    }
}

function drawLineLength() {
    if (e === 0) { // spirograph color pallete
        stroke("#65cdca");
    }

    else if (e === 1) { // epitrochoid color pallete
        stroke("#c26571");
    }

    else if (e === 2) { // other cool equation color pallete
        stroke("#a0e3b9")
    }

    line(width/2 + r12, height/2, width/2 + r12 - lineNum, height/2);
    ellipse(width/2 + r12, height/2, 2, 2);
    ellipse(width/2 + r12 - lineNum, height/2, 3, 3);
}

function exampleCircles() {
    strokeWeight(2);
    noFill();
    // radius 1 circle
    stroke(0);
    ellipse(width/2, height/2, 2*r1Num, 2*r1Num);

    // radius 2 circle
    if (e === 0) { // spirograph
        stroke("#3f807e");
    }

    else if (e === 1) { // epitrochoid
        stroke("#82444c");
    }

    else if (e === 2) { // other cool equation
        stroke("#3d5747")
    }

    
    if ((e === 0) || (e === 2)) { // spirograph -- circles inside
        r12 = r1Num - r2Num;
    }

    else { // epitrochoid -- cirlces outside
        r12 = r1Num + r2Num;
    }

    ellipse(width/2 + r12, height/2, 2*r2Num, 2*r2Num);
    
}

function choosePenColor() {
    if (choosing) {
        noStroke();
        fill(255);
        rect(0 ,0, width, height);
        
        // the six color gradients
        gradient();

        // color box to see which color is clicked
        stroke(0);
        strokeWeight(2);
        fill(userCol);
        rect(445, 350, 30, 30);
    }
}

function checkRadii() {
    if (diffRadii == false) {
        noStroke();
        if (e === 0) { // spirograph
            fill("#65cdca");
        }

        else if (e === 1) { // epitrochoid
            fill("#c26571");
        }

        else if (e === 2) { // other cool equation
            fill("#a0e3b9");
        }
        
        textSize(18);
        text("Please choose two different radii", diffRadX, diffRadY);
    }
}

function spirograph() {
    // update spirograph variables according to user input
    r1 = r1Num;
    r2 = r2Num;
    p = lineNum;
    k = r2 / r1;

    x1 += scaleN*(r1 - r2)*cos(k*i) + p * cos((1-k)*i);
    y1 += scaleN*(r1-r2)*sin(k*i) - p * sin((1-k)*i);
    
    
    strokeWeight(2);
    stroke(userCol);
    // draw small portion of design
    line(x2, y2, x1, y1);
    noStroke();

    x2 = x1;
    y2 = y1;
}

function epitrochoid() {
    r1 = r1Num;
    r2 = r2Num;
    p = lineNum;
    a = r1 + r2;
    b = a / r2;
    scaleN = .9;

    x1 += scaleN*a*cos(i) - p * cos(b*i);
    y1 += scaleN*a*sin(i) + p * sin(b*i);

    stroke(userCol);
    strokeWeight(2);
    line(x2, y2, x1, y1); // draw small portion of design
    noStroke();
    x2 = x1;
    y2 = y1;
}

function other() {
    // update spirograph variables according to user input
    r1 = r1Num;
    r2 = r2Num;
    p = lineNum;
    l = p / r1;
    k = r2 / r1;
    scaleN = 2;

    x1 += scaleN*r1*((1-k)*Math.cos(i) + l*k*cos(i*((1-k)/k)));
    y1 += scaleN*r1*((1-k)*Math.sin(i) + l*k*sin(i*((1-k)/k)));
    
    stroke(userCol);
    strokeWeight(2);
    line(x2, y2, x1, y1); // draw small portion of design
    noStroke();
    x2 = x1;
    y2 = y1;
}

function makeAndDrawButtons() {
    // make the buttons
        var drawButton = makeButton(7/9 * width, 6/7 * height, 4 * eqX, eqY, "rect");
        drawButton.color(0);
        buttons.push(drawButton);

        var equationB = makeButton(eqX, 7/8 * height, diffRadX, eqY - 5, "rect");
        equationB.color(0);
        buttons.push(equationB);

        // draw all the buttons
        for (var b = 0; b < buttons.length; b++) {
            buttons[b].draw();  
        }
}

function makeTextForButtons() {
    // make text for buttons
        var textOnButton = makeText("DRAW", 7/9 * width + 9, height - eqY - 5, eqX);
        textOnButton.color(240);
        buttonText.push(textOnButton);

        var spiro = makeText("SPIROGRAPH", eqX * 2, height - eqY - 1, 16);
        spiro.color("#65cdca");
        equationText.push(spiro);

        var epi = makeText("EPITROCHOID", eqX * 2, height - eqY - 1, 16);
        epi.color("#c26571");
        equationText.push(epi);

        var other = makeText("COOL EQUATION 3", eqX + 6, height - eqY - 1, 15);
        other.color("#a0e3b9");
        equationText.push(other);

        var radius1 = makeText("Radius 1", eqX * 2, eqY, 18);
        radius1.color(0);
        buttonText.push(radius1);

        radius2 = makeText("Radius 2", rad2X, eqY, 18);
        radius2.color("#3f807e");
        buttonText.push(radius2);

        lineLen = makeText("Line Length", llX, eqY, 18);
        lineLen.color("#65cdca");
        buttonText.push(lineLen);
        
}

function drawText() {
    textAlign(LEFT);

    // change color pallete based on math equation
    
    if (e === 1) { // purple-pink: epitrochoid
        lineLen.color("#c26571");
        radius2.color("#753d45")
    }

    else if (e === 2) {
        lineLen.color("#a0e3b9");
        radius2.color("#3d5747");
    }

    // draw the button's text
    for (var t = 0; t < buttonText.length; t++) {
        buttonText[t].draw();
    }
}

function radiusSliders() {
    ellipseMode(CENTER);
    stroke(sliderCol);
    strokeWeight(3);
    // radius 1
    line(r1Min, ry, r1Max, ry);
    noStroke();
    fill(0);
    r1x = constrain(r1x, r1Min, r1Max);
    ellipse(r1x, ry, rd, rd);
    textAlign(CENTER);
    r1Num = floor(map(r1x, r1Min, r1Max, radMin, rad1Max));
    text(str(r1Num), r1x, ry + 2 * rd);

    // radius 2
    stroke(sliderCol);
    strokeWeight(3);
    line(r2Min, ry, r2Max, ry);
    noStroke();
    fill(0);
    r2x = constrain(r2x, r2Min, r2Max);
    ellipse(r2x, ry, rd, rd);
    r2Num = floor(map(r2x, r2Min, r2Max, radMin, rad2Max));
    text(str(r2Num), r2x, ry + 2 * rd);

    // line length
    stroke(sliderCol);
    strokeWeight(3);
    line(pMin, ry, pMax, ry);
    noStroke();
    fill(0);
    px = constrain(px, pMin, pMax);
    ellipse(px, ry, rd, rd);
    lineNum = floor(map(px, pMin, pMax, llMin, llMax));
    text(str(lineNum), px, ry + 2 * rd);

    // radii can't be same size
    if (r1Num === r2Num) {
        diffRadii = false;
    }
    
    else {
        diffRadii = true;
    }
}


// button for the user to chose their pen color
function chooseColor() {
    stroke(0);
    strokeWeight(2);
    fill(userCol);
    rect(colorX, colorY, eqY, eqY);
}

function gradient() {
    //gradient red to orange
    for (var r = 0; r < gradSection; r += 2) {
        var startR = color(255, 0, 0); // red
        var endO = color(255, colorMid, 0); // orange
        for (var c = 0; c < height; c += 2) {
            var interCol1 = lerpColor(startR, endO, r/(width/6));
            var white = color(255);
            var interLight1 = lerpColor(interCol1, white, c/height);
            fill(interLight1);
            rect(r, c, 2, 2);
        }
    }

    // gradient orange to yellow
    for (var r = 0; r < gradSection; r += 2) {
        var startO = color(255, colorMid, 0); // orange
        var endY = color(255, 255, 0); // yellow
        for (var c = 0; c < height; c += 2) {
            var interCol2 = lerpColor(startO, endY, r/(width/6));
            var interLight2 = lerpColor(interCol2, white, c/height);
            fill(interLight2);
            rect(r + gradSection, c, 2, 2);                
        }
    }

    // gradient yellow to green
    for (var r = 0; r < gradSection; r += 2) {
        var startY = color(255, 255, 0); // yellow
        var endG = color(0, 255, 0); // green
        for (var c = 0; c < height; c += 2) {
            var interCol3 = lerpColor(startY, endG, r/(width/6));
            var interLight3 = lerpColor(interCol3, white, c/height);
            fill(interLight3);
            rect(r + 2 * gradSection, c, 2, 2);               
        }
    }

    // gradient green to blue
    for (var r = 0; r < gradSection; r += 2) {
        var startG = color(0, 255, 0); // green
        var endB = color(0, 0, 255); // blue
        for (var c = 0; c < height; c += 2) {
            var interCol4 = lerpColor(startG, endB, r/(width/6));
            var interLight4 = lerpColor(interCol4, white, c/height);
            fill(interLight4);
            rect(r + 3 * gradSection, c, 2, 2);               
        }
    }

    // gradient blue to purple
    for (var r = 0; r < gradSection; r += 2) {
        var startB = color(0, 0, 255); // blue
        var endPp = color(colorMid, 0, colorMid); // purple
        for (var c = 0; c < height; c += 2) {
            var interCol5 = lerpColor(startB, endPp, r/(width/6));
            var interLight5 = lerpColor(interCol5, white, c/height);
            fill(interLight5);
            rect(r + 4 * gradSection, c, 2, 2);               
        }
    }

    // gradient purple to pink
    for (var r = 0; r < gradSection; r += 2) {
        var startPp = color(colorMid, 0, colorMid); // purple
        var endPk = color(255, eqX, colorPink); // pink
        for (var c = 0; c < height; c += 2) {
            var interCol6 = lerpColor(startPp, endPk, r/(width/6));
            var interLight6 = lerpColor(interCol6, white, c/height);
            fill(interLight6);
            rect(r + 5 * gradSection, c, 2, 2);               
        }
    }
}

function displayEquation() {
    // switch between the 2 equations

        if (equationCount % 3 === 1) {
            e = 0; // spirograph
        }

        else if (equationCount % 3 === 2) {
            e = 1; // Epitrochoid
        }

        else if (equationCount % 3 === 0) {
            e = 2;
        }

        // draw the equation name
        eText = equationText[e];
        fill(eText.tColor);
        textSize(eText.size);
        text(eText.t, eText.x, eText.y);
}

// back button to setting screen
function drawBackButton() {
	var backButton = makeButton(backB, backB, backB, backB, "ellipse");
		backButton.color(0);
        noStroke();
		backButton.draw();
		stroke(255);
		strokeWeight(2);
        // arrow
		line(backBX, backB, backB, backB + 8);
		line(backBX, backB, backB, backBX + 1);
		line(backBX, backB, backB + 9, backB);
}

// Object: Creates Buttons
function makeButton(bx, by, bw, bh, bShape) {
	var button = {x: bx, y: by, bColor: color(0),
				  shape: bShape, w: bw, h: bh,
				  draw: displayButton, color: setbColor}
	return button
}

// draws the buttons
function displayButton() {
	fill(this.bColor);
	if (this.shape == "rect") {
		rect(this.x, this.y, this.w, this.h);
	}
	else if (this.shape === "ellipse") {
		ellipse(this.x, this.y, this.w, this.h);
	}
}

// sets the button color
function setbColor(c) {
	this.bColor = color(c);
}

// Object: Creates text
function makeText(input, tx, ty, tSize) {
	var textForButton = {x: tx, y: ty, size: tSize, tColor: color(backCol),
						 t: input, draw: displayText, color: setTColor}
	return textForButton;
}

// draw the text
function displayText() {
	fill(this.tColor);
	textSize(this.size);
	text(this.t, this.x, this.y);
}

// set the text color
function setTColor(c) {
	this.tColor = color(c);
}

function mousePressed() {

	// click draw button to go to draw mode
	if ((mouseX > 7/9 * width) & (mouseX < 7/9 * width + 80) 
		&& (mouseY > 6/7 * height) && (mouseY < 6/7 * height + 30)
		&& (drawing == false) && (diffRadii)) {
		drawing = ! drawing;
		justClicked = true;
	}

    // back button -- send to settings screen
	else if (dist(mouseX, mouseY, backB, backB) <= backB / 2) {
		drawing = false;
	}

    // 3 math equations -- button to rotate the math equations
    else if ((mouseX > eqX) & (mouseX < eqX + eqW) 
        && (mouseY > 7/8 * height) && (mouseY < 7/8 * height + eqY - 5)
        && (drawing == false)) {
        equationCount += 1;
    }

    // drag radius 1 slider
    if (dist(r1x, ry, mouseX, mouseY) < rd / 2) {
        dragging = true;
        rad1 = true;
        justClicked = false;
        drawing = false;

    }

    // drag radius 2 slider
    else if (dist(r2x, ry, mouseX, mouseY) < rd / 2) {
        dragging = true;
        rad2 = true;
        justClicked = false;
        drawing = false;
    }

    // drag line length slider
    else if (dist(px, ry, mouseX, mouseY) < rd / 2) {
        print("t");
        dragging = true;
        lineL = true;
        justClicked = false;
        drawing = false;

    }

    // click inside color box
    if ((mouseX <= colorX + eqY) & (mouseX >= colorX)
        && (mouseY <= colorY + eqY) && (mouseY >= colorY) 
        && drawing === false) {
        choosing = true;
    }

    // set pen color to user's click
    if (choosing) {
        userCol = color(get(mouseX, mouseY));
    }
}

function mouseReleased() {
    dragging = false;
    rad1 = false;
    rad2 = false;
    lineL = false;
}

function keyPressed() {
    // use left arrow key to go back to the settings screen
    if ((drawing) & (keyCode === LEFT_ARROW)) {
        drawing = false;
    }

    // set pen color by hitting enter key
    if ((choosing) & (keyCode === ENTER)) {
        choosing = false;
    }
}

Sean Meng-Final Project

hmeng-final project

//Sean Meng
//hmeng@andrew.cmu.edu
//Section C
//Final Project

var mySoundA;
var amp;
var vol = [];

function preload() {
    //Load music Love Lockdown
    mySoundA = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/Love_Lockdown-online-audio-converter.com.wav");
    mySoundA.setVolume(2);
}

function setup() {
    createCanvas(500, 500);
    //define amplitude and frequency to visualize
    amplitude = new p5.Amplitude();
    fft = new p5.FFT();
    mySoundA.amp(0.2);    
    frameRate(200);
}

function draw() {
    //size of the button
    var bSize = 20;
    background(218, 227, 226);
    noStroke();

//Album art background
    fill(250);
    rect(0, 0, 100, 500);

    fill(128, 15, 120);
    rect(85, 0, 15, 45);
    
    fill(34, 32, 99);
    rect(85, 45, 15, 45);  
    
    fill(242, 235, 97);
    rect(85, 90, 15, 45);   

    fill(141, 214, 204);
    rect(85, 135, 15, 45); 

    fill(92, 182, 224);
    rect(85, 180, 15, 45); 

    fill(53, 156, 120);
    rect(85, 225, 15, 45); 

    fill(242, 182, 241);
    rect(85, 270, 15, 45); 
    
    fill(197, 204, 124);
    rect(85, 315, 15, 45); 

    fill(181, 103, 180);
    rect(85, 360, 15, 45); 

    fill(184, 44, 116);
    rect(85, 405, 15, 45);  
    
    fill(49, 6, 92);
    rect(85, 450, 15, 50);      

//PAUSE button
    fill(0);
    rect(10, height - 30, bSize, bSize);

//PLAY button
    fill(0);
    triangle(10, height - 60, 10, height - 40, 30, height - 50);

//Spectrum represents amplitude
    let spectrum = fft.analyze();
    noStroke();
    fill(255); 
    for (var i = 0; i< spectrum.length; i++){
        let x4 = map(i, 0, spectrum.length, 100, width * 3.5);
        let h4 = -height + map(spectrum[i], 0, 255, height * 0.95, 0);
        rect(x4, height, width / spectrum.length, h4 )
    }

//Beating heart graphic represents amplitude
    let level = amplitude.getLevel();
    let offset = map(level, 0, 1, 0, 80);

//draw first half of the heart    
    strokeWeight(2);
    stroke(220, 30, 30);
    fill(220, 30, 30);
    beginShape();
    vertex(240 - offset, 180 - offset);
    vertex(270 - offset, 165 - offset);
    vertex(300, 180 - offset);
    vertex(330 + offset, 160 - offset);
    vertex(355 + offset, 170 - offset);   
    vertex(375 + offset, 200);
    vertex(355 + offset, 240);
    vertex(330 + offset, 270);
    vertex(290, 335 + offset);
    vertex(275 - offset, 280);
    vertex(240 - offset, 240);    
    vertex(220 - offset, 210);
    vertex(240 - offset, 180 - offset);
    endShape();

//Draw second half of the heart
    strokeWeight(2);    
    stroke(115, 20, 15);
    fill(115, 20, 15);
    beginShape();
    vertex(300, 180 - offset);
    vertex(330 + offset, 160 - offset);
    vertex(355 + offset, 170 - offset);   
    vertex(375 + offset, 200);
    vertex(355 + offset, 240);
    vertex(330 + offset, 270);
    vertex(290, 335 + offset);
    vertex(305 + offset, 270);
    vertex(290 - offset, 245); 
    vertex(300 + offset, 215);        
    vertex(275 - offset, 200);
    vertex(300, 180 - offset);
    endShape();

//Five waveform that visualzie frequency
    //wave A
    let waveform = fft.waveform();
    noFill();
    beginShape(POINTS);
    stroke(150, 10, 10);
    strokeWeight(2);
    for(var i = 0; i < waveform.length; i++){
        let x0 = map(i, 0, waveform.length, 100, width);
        let y0 = map(waveform[i], - 3, 3, 0, height);
        vertex(x0, y0);
    }
    endShape();

    //wave B
    beginShape(POINTS);
    stroke(180, 10, 10);
    strokeWeight(2);
    for(var i = 0; i < waveform.length; i++){
        let x0 = map(i, 0, waveform.length, 100, width);
        let y0 = map(waveform[i], - 1.5, 1.5, 0, height);
        vertex(x0, y0);
    }
    endShape();
    
    //Wave C
    beginShape(POINTS);
    stroke(220, 30, 30);
    strokeWeight(2);
    for(var i = 0; i < waveform.length; i++){
        let x1 = map(i, 0, waveform.length, 100, width);
        let y1 = map(waveform[i], - 0.7, 0.7, 0, height);
        vertex(x1, y1);
    }
    endShape();

    //Wave D
    beginShape(POINTS);
    stroke(230, 50, 50);
    strokeWeight(1);
    for(var i = 0; i < waveform.length; i++){
        let x2 = map(i, 0, waveform.length, 100, width);
        let y2 = map(waveform[i], - 0.4, 0.4, 0, height);
        vertex(x2, y2);
    }
    endShape();

    //Wave E
    beginShape(POINTS);
    stroke(230, 90, 90);
    strokeWeight(0.5);
    for(var i = 0; i < waveform.length; i++){
        let x2 = map(i, 0, waveform.length, 100, width);
        let y2 = map(waveform[i], - 0.2, 0.2, 0, height);
        vertex(x2, y2);
    }
    endShape();

    //Title of the album
    push();
    translate(75, 250);
    rotate(- PI / 2);
    stroke(65);
    fill(65);
    textStyle(BOLDITALIC);
    textSize(25);
    text('808s & Heartbreaks', 0, 0);
    pop();
}

function mousePressed() {
    //play the song when buttonA is clicked
    if(mouseX > 10 & mouseX < 30 && mouseY > height - 60 && mouseY < height - 40){
        mySoundA.play();
    } 
    //pause the song when buttonB is clicked
    if(mouseX > 10 & mouseX < 30 && mouseY > height - 30 && mouseY < height - 10){
        mySoundA.pause();
    }     
}    

In this project, I intend to homage to my favorite artist of all time Kanye West. The project represents a visualization of his song Love Lockdown from his renowned album 808’s & Heartbreaks. The representation and graphic elements are inspired by the original album cover that designed by artist Kaws. While the beating heart visualizes the amplitude of the music, the waveforms which has a gradient of both color and stroke weight visualizes the frequency of the song. As the song goes, the frequency gets increasingly complicated and generates intriguing pattern.

The original album cover by Kaws
Visualization at 02:37
Concept sketches