Final Project

sketch

//Cora Hickoff
//Section D
//chickoff@andrew.cmu.edu
//Final-Project

//image of dog
var imgD;
//image of fish
var imgF;

//for iterating through dog and fish photos
var num = 0;

//images of dog
var loadedImagesD = [];
//images of fish
var loadedImagesF = [];

//for dragging mouse
var xarray = [];
var yarray = [];

//variables for moth
var x;
var y;
var dx;
var dy;

//variables for blue moth
var w;
var z;
var dw;
var dz; 

//variables for bee
var b;
var p;
var db;
var dp;

function preload() {

    var backgroundImageURL = "https://i.imgur.com/qDrD310.png";
    backgroundIMG = loadImage(backgroundImageURL);

    var sunImageURL = "https://i.imgur.com/6SDAJjt.png";
    sunIMG = loadImage(sunImageURL);

    var mothImageURL = "https://i.imgur.com/bGUODEv.png?1";
    mothIMG = loadImage(mothImageURL);

    var bluemothImageURL = "https://i.imgur.com/FR3gCsQ.png";
    bluemothIMG = loadImage(bluemothImageURL);

    var beeImageURL = "https://i.imgur.com/oTcCy45.png";
    beeIMG = loadImage(beeImageURL);

        //dog photos
        for (var i = 0; i < dogPhotos.length; i++) {
            loadedImagesD.push(loadImage(dogPhotos[i]));
        }

        //fish photos
        for (var i = 0; i < fishPhotos.length; i++) {
            loadedImagesF.push(loadImage(fishPhotos[i]));
        }
}

function setup() {

    createCanvas(700, 500); 

        var d = floor(random(0, dogPhotos.length));
        var f = floor(random(0, 0, fishPhotos.length));

        //images of dog
        imgD = loadedImagesD[d];
        //images of fish
        imgF = loadedImagesF[f];

        x = random(width);
        y = random(height);
        dx = random(-5, 5);
        dy = random(-5, 5);

        w = random(width);
        z = random(height);
        dw = random(-5, 5);
        dz = random(-5, 5);

        b = random(width);
        p = random(height);
        db = random(-5, 5);
        dp = random(-5, 5);
}

function draw() {

    background(200); 

    //photo of background
    image(backgroundIMG, 0, 0, 0);
    //photo of sun
    image(sunIMG, 0, 0, 0);
    //photo of dog
    image(imgD, 0, 0, imgD.width, imgD.height);
    //photo of fish
    image(imgF, 0, 0, imgF.width, imgF.height);

    //drags smaller dog image along canvas
    for (var i = 0; i < xarray.length; i++) {
        fill(0);
        image(imgD, xarray[i], yarray[i], imgD.width/2.4, imgD.height/2.4);
    }
    
    if (xarray.length > 8) {
        xarray.shift(1); 
        yarray.shift(1);
    }

    //photo of moth
    image(mothIMG, x, y, mothIMG.width/2.3, mothIMG.height/2.3);

        x += dx;
        y += dy;

        //if image exceeds canvas width,
        //set back to 0
        if (x > width) x = 0;
        else if (x < 0) x = width;
        //if image exceeds canvas height,
        //set back to 0
        if (y > height) y = 0;
        else if (y < 0) y = height;

    //photo of blue moth
    image(bluemothIMG, w, z, bluemothIMG.width/1.9, bluemothIMG.height/1.9);

        w += dw;
        z += dz;

        //if image exceeds canvas width,
        //set back to 0
        if (w > width) w = 0;
        else if (w < 0) w = width;
        //if image exceeds canvas height,
        //set back to 0
        if (z > height) z = 0;
        else if (z < 0) z = height;

    //photo of bee
    image(beeIMG, b, p, beeIMG.width/2.5, beeIMG.height/2.5);

        b += db;
        p += dp;

        //if image exceeds canvas width,
        //set back to 0
        if (b > width) b = 0;
        else if (b < 0) b = width;
        //if image exceeds canvas height,
        //set back to 0
        if (p > height) p = 0;
        else if (p < 0) p = height;

    //lightens screen when mouse over sun
    if (mouseX <= 398 & mouseX >= 320 && mouseY >= 30 && mouseY <= 105) {

        rectMode(CORNER);
        noStroke();
        fill(246, 215, 161, 70);
        rect(0, 0, 700, 500);
    }
}

function mouseDragged() {

    xarray.push(mouseX);
    yarray.push(mouseY);
}

function mousePressed() {

    //iterates through dog photos when mouse clicks its body
    if (mouseX <= 500 & mouseX >= 150 && mouseY >= 275 && mouseY <= 400) {
        var d = num % dogPhotos.length;
        imgD = loadedImagesD[d];
        num++;
    }

    //iterates through fish photos when mouse clicks blanket
    if (mouseX <= 700 & mouseX >= 0 && mouseY >= 130 && mouseY <= 250) {
        var f = num % fishPhotos.length;
        imgF = loadedImagesF[f];
        num++;
    }
}

var dogPhotos = [

    //rusty-colored dog
    "https://i.imgur.com/2vglMnn.png",
    //white/pink dog
    "https://i.imgur.com/IWbYamo.png",
    //lilac dog
    "https://i.imgur.com/I5xU7LF.png",
    //black dog
    "https://i.imgur.com/AAQQgCj.png",
    //blue dog
    "https://i.imgur.com/CTZSr9D.png",
    //mulberry dog
    "https://i.imgur.com/kt5rN0R.png"]

var fishPhotos = [
    
    //first fish
    "https://i.imgur.com/bD3GBjE.png",
    //second fish
    "https://i.imgur.com/eUWa3dx.png",
    //third fish
    "https://i.imgur.com/XJFlBTd.png"]
    

https://vimeo.com/246466644

Final Project Still

When I started this project, I knew that I wanted to give users a hands-on experience, similar to the  I Spy computer games that I’d play as a kid, which I drew inspiration from. The worlds created in these games still felt genuine despite the fact that they were within a computer screen. This is in part because photos from real life were used.

Moreover, I really loved the Mixies Assignment and that it felt like we were playing with puzzle pieces and working with our hands, even though we were doing this electronically. This is why I chose to use photos that I’ve taken and use similar methods from that assignment to make this project interactive and fun.

To download this project, click this zip file: chickoff-final-project

daphnel- Final Project- Section D

Final

//Daphne Lee
//15-104::1 (9:30am) Section D
//daphnel@andrew.cmu.edu
//Final-Project

//x is x location of ball;
//y is y location of ball;
var x = 200;
var y = 200;
var dirx = 1;
var diry = 5;
var speed = 0.75;
var paddleWidth = 75;
var paddleHeight = 10;
var ballDiam = 20;
var score = 0;
var lives = 3;
var scaled = 0.6;

var blockRowCount = 4;
var blockColCount = 13;
var blockWidth = 50;
var blockHeight = 20;
var blockPadding = 10;
var blockOffsetX = 30;
var blockOffsetY = 10;

var blockXArr = [];
var blockYArr = [];
var statusArr = [];
var started = false;

//preloaded items
var bg;
var girlLeft;
var girlRight;
var girlYPosition = 150;
var girlsSize = 100;
var press;
var enter;

function preload() {
    bg = loadImage("https://i.imgur.com/kElOb6m.jpg");
        //items on the start page before game starts
        if(started==false){
            press = loadImage("https://i.imgur.com/kbAP99M.png");
            enter = loadImage("https://i.imgur.com/4ijF2zc.png")
            // the girl gifs on the start screen
            girlLeft = createImg("https://i.imgur.com/IjEVc03.gif");
            girlLeft.position(150 * scaled, girlYPosition * scaled);
            girlLeft.size(girlsSize, girlsSize)
            girlRight = createImg("https://i.imgur.com/IjEVc03.gif");
            girlRight.position(500 * scaled, girlYPosition * scaled);
            girlRight.size(girlsSize, girlsSize);
        }
}

function setup() {
    createCanvas(800, 400);
    for(var i = 0; i < blockRowCount * blockColCount; i++) {
        //status makes sure if blocks disappear or remain
        statusArr.push(1);
    }
}

function collision(){
    for(var c = 0; c < blockColCount; c++){
        for(var r = 0; r < blockRowCount; r++){
            if(statusArr[r * blockColCount + c] == 1) {
                var radius = ballDiam / 2;

                //creating the blocks;
                var blockX = c * (blockWidth + blockPadding) + radius
                var blockY = r * (blockHeight + blockPadding) + radius;

                //collision points for each block;
                var minXCollide = blockX - radius;
                var maxXCollide = blockX + radius + blockWidth;
                var minYCollide = blockY - radius;
                var maxYCollide = blockY + radius + blockHeight;

                var collidesX = (x > minXCollide & x < maxXCollide);
                var collidesY = (y > minYCollide & y < maxYCollide)

                //what happens as a result of the collision;
                if(collidesX & collidesY) {
                    diry = -diry;
                    score++;
                    statusArr[r * blockColCount + c] = 0;
                }
            }
        }
    }
}

function countScore(){
    stroke(255);
    strokeWeight(1);
    textSize(15);
    //gives you a score when you lose
    text("Score: " + score, width - 70, height - 10);
}

function drawLives(){
    stroke(255);
    strokeWeight(1);
    textSize(15);
    //shows you the number of lives you have
    text("Lives: " + lives, 10, height - 10);
}

//creating the end result of what happens if you destroy all the blocks
function congrats(){
    if(score == blockColCount * blockRowCount){
        fill("lavender");
        textStyle(BOLD);
        textFont("cursive", 50);
        text("Congratulations You Won!", 120, 200);
    }
}

function draw() {
    scale(scaled);
    background(bg);
    noStroke();
    var textWidth = 150;
    var textHeight = 50;

    //creates the beginning press enter text before the game starts
    if(started == false){
        image(press, 340, 150, textWidth, textHeight);
        image(enter, 340, 210, textWidth, textHeight);
    }

    if(started){
        //ping pong ball
        rectMode(CENTER);
        fill(255);
        ellipse(x, y, ballDiam, ballDiam);

        //the paddle on the bottom
        fill(100, 300);
        rect(mouseX * scaled * 3, height - paddleHeight, paddleWidth,
        paddleHeight);

        //moves the ball
        x += dirx * speed;
        y += diry * speed;

        //left and right wall boundaries
        if(x > width - ballDiam / 2 || x < ballDiam / 2) {
            dirx = -dirx;
        }
        //top wall boundary
        if(y < ballDiam / 2){
            diry = -diry;
        }

        // else if(y > height + ballDiam / 2){
        if(lives > 0 & y > height + ballDiam / 2){
            x = width / 2;
            y = height / 2;
            lives --;
        } else if(lives == 0){
            speed = 0;
            stroke(0);
            fill("lavender");
            textStyle(BOLD);
            textFont("cursive", 50);
            //creating text to show if you fail to complete game
            text("GAME OVER", 250, 200);
            textSize(20);
            text("Score: " + score, 350, 250);
        }

        //Collision detection for the paddle
        var radius = ballDiam / 2;
        var minXCollide = (mouseX * scaled * 3) - radius - paddleWidth / 2;
        var maxXCollide = (mouseX * scaled * 3) + radius + paddleWidth / 2;
        var minYCollide = (height - paddleHeight) - radius - paddleHeight / 2;
        var maxYCollide = (height - paddleHeight) + radius + paddleHeight / 2

        var collidesX = (x >= minXCollide & x <= maxXCollide);
        var collidesY = (y >= minYCollide & y <= maxYCollide)

        if(collidesX && collidesY) {
            if(diry > 0) {
                diry = -diry;
                dirx = random(-5, 5);
                dirx = -dirx;
            }
        }

        countScore();
        drawLives();
        rectMode(CORNER);

        //creating the blocks
        for(var c = 0; c < blockColCount; c++){
            for(var r = 0; r < blockRowCount; r++) {
                if(statusArr[r * blockColCount + c] == 1) {
                    var blockX = c * (blockWidth + blockPadding) + ballDiam / 2;
                    var blockY = r * (blockHeight + blockPadding) + ballDiam / 2;
                    fill(100, 100);
                    stroke(255);
                    strokeWeight(1);
                    rect(blockX, blockY, blockWidth, blockHeight);
                }
            }
        }
        collision();
        congrats();
    }
}

function keyPressed() {
    // start the game
    if(keyCode == 13){
        //hides the girls running in the beginning frame before the game starts
        girlLeft.hide();
        girlRight.hide();
        started = true;
    }
}

I had a lot of ideas for my proposal but I found implementing the ideas I had difficult. For my project, I focused on keeping it at one level. You start out with three lives and whenever you die, the ball will reset at the middle of the canvas and move downwards from there. Once the 3 chances are used, it’s game over. I made it so that even if you are late in hitting the ball and you hit the left or right edge of the paddle, the ball could still be saved and move back up. As long as any contact with the paddle is made, the ball will be in play. When two side by side blocks are simultaneously hit by a ball due to the ball hitting the blocks directly in between the blocks, both blocks will disappear and the ball will continue moving upwards or diagonally until it has reached a solid border like the wall or the edge of another block.

Some Key Points

  1. Note that the ball moves randomly at all times so you need to make sure to keep your focus on the direction of the ball at all times.
  2.  Refresh the page to play the game again.
  3. The ball is reset in the middle of the screen when you die and will immediately start moving again towards a random downwards direction.

For Graders:: TIP! Playing this game takes a while so if you would like, you can increase the PaddleWidth from 75 to 800 or 900 and center it on the screen and let it just run itself until the blocks are all gone.

This game does not work as well on WordPress due to some parts of the code that could not be scaled well. Please click below for the Zip File to the full size of the game.

Click Here for the Game

rmanagad-finalproject-sectione

sketch

//Robert Managad
//Section-E
//rmanagad@andrew.cmu.edu
//Final Project -- Trigonometric Loading Icons

//This code loops on the basis of the trigonometric functions cosine, sine, and tangent.
//It can be modified to produce three distinct animations, depending on the trig function used,
// and on the axis be affected.


var spins = [];
var drips = [];
var warps = [];
var pluss = [];

function setup() {
	createCanvas(420, 420);

	//Spin Loop, center
	push();
	for (var i = 0; i < 12; i++){
		var spinposition = createVector(i * 20, i);
		var spinradius = i * 1; // Radius increases by 200% for every iteration of i, up to 12.
		spins[i] = new Spin(spinposition, spinradius); //holds circle function in the array
	}  
	pop();

	//Drip loop, top center
	for (var i = 0; i < 8; i++){
		var dripposition = createVector(i*18, i);
		var dripradius = i * 2;
		drips[i] = new Drip(dripposition, dripradius);
	}

	//Warp loop, left center
	for (var i = 0; i < 12; i++){
		var warpposition = createVector(i*20, i);
		var warpradius = i * 1.5;
		warps[i] = new Warp(warpposition, warpradius);
	}

	//Plus loop, left center
	for (var i = 0; i < 12; i++){
		var plusposition = createVector(i*20, i);
		var plusradius = i * 1.5;
		pluss[i] = new Plus(plusposition, plusradius);
	}
}

function draw() {
	background(0);

	//drip draw
	for(var i = drips.length - 1; i >= 0; i--){
		var drip = drips[i];
		drip.update();
		drip.display();
	}  

	//rectangle mask
	fill(0);
	noStroke();
	rect(140, 130, 140, 300);

	//warp draw
	for(var i = warps.length - 1; i >= 0; i--){
		var warp = warps[i];
		warp.update();
		warp.display();
	}  

	//spin draw
	for(var i = spins.length - 1; i >= 0; i--){
		var spin = spins[i];
		spin.update();
		spin.display();
	}  

	//plus draw
	for(var i = pluss.length - 1; i >= 0; i--){
		var plus = pluss[i];
		plus.update();
		plus.display();
	}  
}

//--------------------

//elements of each circle are compounded into the Spin function.
function Spin(spinposition, spinradius){
  this.position = spinposition;
  this.radius = spinradius;
  this.direction = 1;
  this.time = 0; //controls the placement of the starting anchor, time to jump towards.
  //updates position every time draw is called.
  this.update = function(){
	this.time += this.direction * this.radius * 0.007; //holds value of velocity. Higher radius value = higher speed.
	this.position.y = (200 + 90 * cos(this.time))/2;
	this.position.x = (200 + 90 * sin(this.time))/2;
	//trig function directs the animation (slowing down in middle/accelerating the circles as they approach the edges)
  }

  //holds visual presentation
  this.display = function(){
  	noFill();
    stroke(255);
    strokeWeight(1.5);
    ellipse(this.position.x - 20, this.position.y - 20, this.radius, this.radius);  
  }
}

//---------------------

function Drip(dripposition, dripradius){
  this.position = dripposition;
  this.radius = dripradius;
  this.direction = 1;
  this.time = 0; //controls the placement of the starting anchor, time to jump towards.
  //updates position every time draw is called.
  this.update = function(){
	this.time += this.direction * this.radius * 0.004; //holds value of velocity. Higher radius value = higher speed.
	this.position.y = (200 + 90 * tan(this.time))/3;
	//trig function directs the animation (slowing down in middle/accelerating the circles as they approach the edges)
  }

  //holds visual presentation
  this.display = function(){
  	noFill();
    stroke(255);
    strokeWeight(1.5);
    ellipse(this.position.x + 275, this.position.y - 10, this.radius, this.radius);  
  }
}

//------------------------

function Warp(warpposition, warpradius){
  this.position = warpposition;
  this.radius = warpradius;
  this.direction = 1;
  this.time = 0; //controls the placement of the starting anchor, time to jump towards.
  //updates position every time draw is called.
  this.update = function(){
	this.time += this.direction * this.radius * 0.002; //holds value of velocity. Higher radius value = higher speed.
	this.position.y = 200 + 30 * cos(this.time);
	this.position.x = 200 + 30 * tan(this.time);
	//trig function directs the animation (slowing down in middle/accelerating the circles as they approach the edges)
  }

  //holds visual presentation
  this.display = function(){
  	noFill();
    stroke(255);
    strokeWeight(1.5);
    ellipse(this.position.x , this.position.y + 160, this.radius, this.radius);  
  }
}

//----------------------------

function Plus(plusposition, plusradius){
  this.position = plusposition;
  this.radius = plusradius;
  this.direction = 1;
  this.time = 0; //controls the placement of the starting anchor, time to jump towards.
  //updates position every time draw is called.
  this.update = function(){
	this.time += this.direction * this.radius * 0.002; //holds value of velocity. Higher radius value = higher speed.
	this.position.y = 200 + 40 * 1/cos(this.time)/3;
	this.position.x = 200 + 40 * 1/sin(this.time)/3;
	//trig function directs the animation (slowing down in middle/accelerating the circles as they approach the edges)
  }

  //holds visual presentation
  this.display = function(){
  	noFill();
    stroke(255);
    strokeWeight(1.5);
    ellipse(this.position.x , this.position.y, this.radius, this.radius);  
  }
}

If gifs below are frozen: right-click and open the image in a new tab.

Helix loading icon
Warp loading icon
Drip loading icon
Plus loading icon
Spin loading icon
Chain Loading Icon

 

My final project culminated in a series of six loading icons. I used trigonometric functions to calculate x and y positions — because of their cyclical behaviours, sin, cosine, and tangent worked well for looping animations. Individual animation gifs can be seen above. Process work can be seen below

From a design standpoint, I developed these loading icons with several human factors in mind — from longevity and human attention span, to interactivity and engagement. Repetition in form, symmetry in composition and shape, and cyclical rhythm all contribute to keeping people from becoming disengaged with the content. As a component living in a transitionary space, the loading icon serves to bridge one space to the next.

 

Loading icon sketches on Illustrator
initial sketches

jennyzha – final project

Final_Project

sketch

// Jenny Zhang
// jennyzha
// Section D 
// Final Project

var img;
//setting a global variable for picture the user can paint
var col = [0, 0, 0, 0];
//setting a an initial color for the paintbrush color
var aSlider;
//setting a global variable for the slider that will control the width of the brush
var SizeOfBrush = 10;
//setting initial SizeOfBrush for the width of the brush

function preload() {
    var imgs = [];
    //preloading all of the possible images the user can paint into an array

    imgs[0] = "http://i.imgur.com/UyyTNyF.png";
    imgs[1] = "http://i.imgur.com/sW4fWRP.png";
    imgs[2] = "http://i.imgur.com/6HBfsCu.png";    
    imgs[3] = "http://i.imgur.com/60ITEbG.png";
    imgs[4] = "http://i.imgur.com/Zli7OsC.png";
    imgs[5] = "http://i.imgur.com/ztRhRts.png";
    imgs[6] = "http://i.imgur.com/Qx8zJO4.png";    
    imgs[7] = "http://i.imgur.com/mzxbto4.png";
    imgs[8] = "http://i.imgur.com/vXdn15r.png";
    imgs[9] = "http://i.imgur.com/shwrAy5.png";
    imgs[10] = "http://i.imgur.com/manEqm3.png";
    imgs[11] = "http://i.imgur.com/oh8iKpK.png";
    imgs[12] = "http://i.imgur.com/oh8iKpK.png";
    imgs[13] = "http://i.imgur.com/306OVy6.png";
    imgs[14] = "http://i.imgur.com/xJVNo7U.png";
    imgs[15] = "http://i.imgur.com/4mv8uhP.png";
    imgs[16] = "http://i.imgur.com/MvNo2DV.png";
    imgs[17] = "http://i.imgur.com/dxlMoKR.png";
    imgs[18] = "http://i.imgur.com/mxti4c2.png";
    imgs[19] = "http://i.imgur.com/hDtDFhD.png";
    imgs[20] = "http://i.imgur.com/shwrAy5.png";
    
    var num = floor(random(0, imgs.length));
    //randomly choosing a picture from the array to paint
    img = loadImage(imgs[num]);
    //assigning the image to the variable img
}

function setup() {
    createCanvas(800, 650);
    background(145, 200, 200);

    aSlider = createSlider(10, 50, SizeOfBrush);
    aSlider.position(670, 620);
    //creating the slider, placing it at the bottom of the canvas

    fill(250);
    noStroke();
    rect(0, 300, 800, 650); 
    //creating the canvas that the user will draw on 

    fill(145, 200, 200);
    noStroke();
    rect(0, 590, 800, 650); 
    //creating the canvas that the user will draw on 

    fill(0);
    textSize(20);
    text("Paint Away!", 0, 20);
    //writing the title of the page

    fill(0);
    textSize(15);
    text("Click on the painting to choose your color, then paint by clicking on the bottom canvas provided.", 0, 40); 
    //writing the instructions to choosing your color    

    fill(0);
    textSize(15);
    text("Move the slider in the bottom right corner to change the size of your paint brush.", 0, 55); 
    //writing the instructions to choosing your paintbrush size
}

function mousePressed(){
    SizeOfBrush = aSlider.value();
    //setting the width of the brush SizeOfBrush to the slider value
    //this is adapted from lab 15

    if (mouseX > 0 & mouseX < 800 && mouseY > 0 && mouseY < 350) {
        col = get(mouseX, mouseY);
    }
    //creating a restriction that the user can only get their color from the provided image

    else if  (mouseX > 0 & mouseX < 800 && mouseY > 350 && mouseY < 600 - SizeOfBrush/2){
        fill(color(col));
        ellipse(mouseX, mouseY, SizeOfBrush);
    }
    //telling the program that anywhere else besides the picture, they can draw a single ellipse

    fill(145, 200, 200);
    rect(70, 615, 250, 15);
    //effectively "erases"/"refreshes" the text every time the draw function is called

    fill(0);
    textSize(12);
    text("Your brush color is (" + col + ")", 70, 625); 
    //creates a text box telling you your current paintbrush color
    //this is adapted from assignment 11A, text rain
}

function mouseDragged() {
    SizeOfBrush = aSlider.value();
    //setting the brush size to the slider value

    if (mouseX > 0 & mouseY > 0 && 
        mouseX < 800 && mouseY > 300 && 
        mouseY < 600 - SizeOfBrush/2) {
            noStroke();
            fill(color(col));
            //setting the restriction so that when the mouse is dragged the user can draw in the provided canvas area

            ellipse(mouseX, mouseY, SizeOfBrush);
    }
}

function draw() {
    image(img, 0, 60); 
    //place current picture the user will draw

    fill(color(col));
    rect(10,595,50,50);
    //creates the square in the botton that shows the current color the user is using
}

My final project is essentially a virtual coloring book. The steps are very simple and easy. All you have to do is refresh the page if you don’t want to paint the painting provided until you are satisfied with the one loaded. Next, choose your first color to paint with by clicking on the color in the painting. Afterwards, choose the thickness of your brush by sliding the slider in the bottom right corner. Finally, click or drag across the bottom half of the screen, or your “canvas” to draw!

*unfortunately, wordpress is unable to handle the canvas size of the program, that being said, please refer to the attached zip file for the full effect – thank you!*

ashleyc1-Section C-Final Project

RULES:

-Use the mouse (either by pressing or moving around) to interact with animations

-Click any key to cycle through different animations (click within the canvas first if not working because wordpress is weird)

Note: If file is opened through google browser, mouse isn’t limited on first animation and they all generally run smoother

sketch

//Ashley Chan
//Section C
//ashleyc1@andrew.cmu.edu
//Final Project - Type in Motion

/////////////////////////////////////
// MAIN  CONTROL //
///////////////////////////////////

var index = 0;

//global var for images
var revealImg;
var twinkleImg;
var eraseImg;
var sprayHintImage;
var sprayOverlayImage;

function preload() {

//load all the images
revealImg = loadImage("https://i.Imgur.com/giFSIcI.jpg?1");
twinkleImg = loadImage("https://i.imgur.com/hqn6Cv9.jpg?1");
eraseImg = loadImage("https://i.imgur.com/VO4buSz.png");
sprayHintImage = loadImage("https://i.imgur.com/P6LkUET.jpg");
sprayOverlayImage = loadImage("https://i.imgur.com/dr6JWoH.png");

}

function setup() {

    createCanvas(480, 180);
    background(0);

    //index that cycles through animations
    //call each animations' setups 
    //depending on index number
    if(index == 0){
        revealSetup();
    }

    if(index == 1){
        twinkleSetup();
    }

    if(index == 2){
        eraseSetup();
    }

    if(index == 3){
        spraySetup();
    }
}


function draw() {

    //call each animations' draw depending on index number
    if(index == 0) {
        revealDraw();
    }

    if(index == 1){
        twinkleDraw();
    }

    if(index == 2){
        eraseDraw();
    }

    if(index == 3){
        sprayDraw();
    }

}

// Cycles through animations every time 
//any key is pressed
function keyPressed(){

    index = (index + 1)%4;

    setup();

}

////////////////////////////////////////////
// REVEAL  ANIMATION //
///////////////////////////////////////////

//var that will spell out reveal
var revealCircles; 
var revealDots;


function revealSetup(){
    
    //Draw a black rectangle for every animation 
    //because we need to make sure the animations 
    //restart without actually calling setup 
    //and messing everything up
    fill(0);
    rect(0, 0, 480, 180);

    revealCircles = [];
    revealDots = [];

    // iterate through pixels
    image(revealImg, 0, 100);
    revealImg.loadPixels();
    
    for(var i = 0; i < 2 * revealImg.width; i++) {
        for(var j = 0; j < revealImg.height; j++) {

            var revealIndex = i * 2 + (j * revealImg.width)*8;
            
            //locate the dark pixels of underlaying image
            //where there is dark, make a revealCircle
            if (revealImg.pixels[revealIndex] < 200){

                revealDots.push(createVector( i / 2, j * 2));
            }
        }
    }

        var num_circles = 0;
    
    //draw certain number of revealCircles every frame
    while (num_circles < 400){
        
        var c = revealCreateCircle();
    
        if (c) {

            revealCircles.push(c);
            num_circles++;

        }
    }
}


function revealDraw(){

    background(0);
  
    //draw the revealCircles
    for(var i = 0; i < revealCircles.length; i++) {
      
        var x = revealCircles[i].x;
        var y = revealCircles[i].y;
        var r = revealCircles[i].r;

    //calculate distance around mouse
    //any space within radius will be drawn and shown
    var d = dist(x, y, mouseX, mouseY);

    if (d  < 90) {
        //center image
        push();
        scale(.5, .5);
        translate(150, 0);
        revealCircles[i].show();
        pop();

        }
    }
}

//While creating a new revealCircle
//Do not create one inside existing one
function revealCreateCircle(){

    var x;
    var y;
    
    // find a random position to create a revealCircle
    var position = int(random(0, revealDots.length));

    x = revealDots[position].x;
    y = revealDots[position].y;

    var valid = true;

    for (var i = 0; i < revealCircles.length; i++) {

        //Don't draw inside another revealCircle
        // If generated already drawn revealCircle, redo
        if (dist(x, y, revealCircles[i].x, revealCircles[i].y) <= revealCircles[i].r) {

            valid = false;
            break;
        }
    }

    //if no revealCircle drawn at spot, draw one 
    if (valid) {

        return new revealCircle(x, y, width, height);
    }

    return false;
}

//define the circles
function revealCircle(xPos, yPos, gwidth, gheight){

    this.x = xPos;
    this.y = yPos;
    this.r = 8;

    this.width = gwidth;
    this.height = gheight;

    //controls the look of the revealCircles 
    //randomizes color when mouse is pressed
    this.show = function(){

        fill(255);
        noStroke();
        strokeWeight(1);
        ellipse(this.x, this.y, this.r);

        }
}


////////////////////////////////////////////////
//  TWINKLE   ANIMATION //
///////////////////////////////////////////////

//var that will spell out twinkle
var twinkleCircles;
var twinkleDots;


function twinkleSetup(){
    
    fill(0);
    rect(0, 0, 480, 180);

    twinkleCircles = [];
    twinkleDots = [];
    
    // iterate through pixels
    //image(twinkleImg, 0, 100);
    twinkleImg.loadPixels();
    
    //locate the dark pixels of underlaying image
    //where there is dark, make a twinkleCircle
    for(var i = 0; i < 2 * twinkleImg.width; i++) {
        for(var j = 0; j < twinkleImg.height; j++) {

            var twinkleIndex = i * 2 + (j * twinkleImg.width)*8;
            
            if (twinkleImg.pixels[twinkleIndex] < 200){

                twinkleDots.push(createVector( i / 2, j * 2));
            }
        }
    }

    var num_circles = 0;
    
    //draw certain number of twinkleCircles every frame
    while (num_circles < 300){
        
        var c = twinkleCreateCircle();

        if (c) {

            twinkleCircles.push(c);
            num_circles++;

        }

    }
    
    //draw the twinkleCircles
    for(var i = 0; i < twinkleCircles.length; i++) {
      
        var x = twinkleCircles[i].x;
        var y = twinkleCircles[i].y;
        var r = twinkleCircles[i].r;

        //center image
        push();
        scale(.6, .6);
        translate(50, 80);
        twinkleCircles[i].show();
        pop();
        
    }
}


function twinkleDraw(){

    //if mouse pressed, "redraw" circles
    //so that color is randomized
    if(mouseIsPressed) {
        for(var i = 0; i < twinkleCircles.length; i++) {
      
            var x = twinkleCircles[i].x;
            var y = twinkleCircles[i].y;
            var r = twinkleCircles[i].r;

            //center image
            push();
            scale(.6, .6);
            translate(50, 80);
            twinkleCircles[i].show();
            pop();

        }
    }
}

//While creating a new twinkleCircle
//Do not create one inside existing one
function twinkleCreateCircle(){

    var x;
    var y;
    
    // find a random position to create a twinkleCircle
    var position = int(random(0, twinkleDots.length));

    x = twinkleDots[position].x;
    y = twinkleDots[position].y;

    var valid = true;

    for (var i = 0; i < twinkleCircles.length; i++) {

        //Don't draw inside another twinkleCircle
        // If generate already drawn twinkleCircle, redo
        if (dist(x, y, twinkleCircles[i].x, twinkleCircles[i].y) <= twinkleCircles[i].r) {

            valid = false;
            break;
        }
    }

    //if no twinkleCircle drawn at spot, draw one 
    if (valid) {

        return new twinkleCircle(x, y, width, height);
    }

    return false;
}

//define twinkleCircles
function twinkleCircle(xPos, yPos, gwidth, gheight){

    this.x = xPos;
    this.y = yPos;
    this.r = 8;

    this.width = gwidth;
    this.height = gheight;

    //controls the look of the twinkleCircles 
    //randomizes color when mouse is pressed
    this.show = function(){

        stroke(255);
        strokeWeight(1);

        //start out as empty twinkleCircles
        var value = 0;
        fill(value);

        //change the color every time mouse is pressed
        if (mouseIsPressed) {

        value = random(0, 255);

        fill(value, value, value);

        }

        ellipse(this.x, this.y, this.r);

        }
}


////////////////////////////////////////////
// ERASE  ANIMTATION //
///////////////////////////////////////////

//var for erase animation
var eraseLastMinute;
var eraseCurrentMinute;

//eraseIndex for animations
var eraseIndex = 0;


function eraseSetup() {
    //scale(.5, .5);
    
    fill(0);
    rect(0, 0, 480, 180);
    eraseImg.loadPixels();

    eraseLastMinute = minute();
    
    //make for loop to control how many images we are making
    for (i = 0; i < 50; i++) {

        image(eraseImg, random(-50, 800), 
            random(-50, height), 100, 43);

    }
}

function eraseDraw() {

    fill(0);
    noStroke();
    ellipse(mouseX, mouseY, 30, 30);

    //call setup and reset every minute
    eraseCurrentMinute = minute();

    //if a minute has passed, call setup and generate 
    //different arrangement of words
    if (eraseLastMinute != eraseCurrentMinute) {

    eraseSetup();

    }
}

///////////////////////////////////////////
//  SPRAY  ANIMATION //
//////////////////////////////////////////

var sprayDots; 

function spraySetup() {

    fill(0);
    rect(0, 0, 480, 180);
    noCursor();   
    noStroke();   
  
    sprayDots = [];

}

function sprayDraw() {

    image(sprayHintImage, 50, 100);
    sprayHintImage.resize(300, 100);

    background(0);
  
    var position = createVector(mouseX, mouseY);

    //if mouse is pressed, draw a bunch of sprayCircles
    //that move toward the overlaying image
    if (mouseIsPressed) {
    var target = sprayFindPixel();    
    var spraydot = new sprayDot(position, target);

    sprayDots.push(spraydot);

    //allow user to draw a bunch of dots
    if (sprayDots.length > 2000) sprayDots.shift();    

    }  
          //draws the sprayDots
          for (var i = 0; i < sprayDots.length; i++) {

            //make sure sprayDots align with hint image
            push();
            translate(100, 50);
            sprayDots[i].update();
            sprayDots[i].draw();
            pop();

        }   

            //call image of Spray outline
            image(sprayOverlayImage, 100, 50);
            sprayOverlayImage.resize(300, 100);
}

//calculate where the underlying image is dark
//and then draw a spraydot overtop
function sprayFindPixel() {

var x;
var y;

    for (var i = 0; i < 200; i++) {

        x = floor(random(sprayHintImage.width));
        y = floor(random(sprayHintImage.height));
    
        if (red(sprayHintImage.get(x, y)) < 255) break;

  }

  return createVector(x, y);

}

//create sprayDots and define characteristics
function sprayDot(position, target) {

    this.position = position;
    this.target = target;
    this.diameter = random(10, 20);

}

sprayDot.prototype.update = function() {   
  
    this.position = 
    p5.Vector.lerp(this.position, this.target, 0.1);

};

sprayDot.prototype.draw = function() { 
  
    //color of sprayDots
    fill(255);
    ellipse(this.position.x, this.position.y, this.diameter, this.diameter);

};


For this project, I was interested in creating interactive animations that allowed type to be dynamic. I wanted the user to interact with the text based on the actions the words described (erase = erase the words). This project was super challenging and I wish I had more time to generate more interactive animations but I’m overall satisfied with it because I like exploring how to make type more dynamic that I can now use within my own art and design practice.

creyes1-FinalProject

creyes1 Final Project – Beat Machine

//Christopher Reyes
//creyes1@andrew.cmu.edu
//Section D
//Capstone Project

//This program is a reinterpretation of Patatap (www.Patatap.com) created by
//Jono Brandel (jonobr1.com) and Lullatone (www.lullatone.com).

//Animations and drumkit sounds play if a key is pressed on the keyboard
//To differentiate from Patatap, there is a beat loop functionality that
//records the users\'s actions, then plays them in sequence for beatmaking

//DIRECTIONS

//SPEAKERS ON
//Press SPACEBAR to begin loop recording, play drum sounds with KEYS 1-5,
//Press SPACEBAR AGAIN to stop recording and play recorded beat
//Press SPACEBAR TWICE to clear loop

//Note: Records/plays one loop at a time

var introTextX = 30; //Initalizes intro text position, sets to undefined to hide

//Color scheme - RGB values
var softYellow = [248, 249, 197];  //Background
var softPink = [252, 202, 199];    //For bigSlideH
var softViolet = [187, 170, 192];  //For bigSlideV
var lightCyan = [187, 252, 223];   //For rectSlide
var darkerTeal = [85, 200, 190];   //For ringPulse
var transWhite = [255, 255, 255, 100]; //Transparent white for bg rings

//Looping variables and arrays
var actions = []; //Lists actions performed
var actionFrames = []; //Frames on which actions were performed
var actionSounds = []; //Lists sounds to be played
var counter = 0; //Counts frames
var counterMax; //Cap on frame count, signals when to loop
var actionIndex; //Relationship between actions, actionFrames, actionSounds

//Drumkit sound samples: "Urban Drum Samples" by user Biochron of soundpacks.com
//Source Link: https://soundpacks.com/free-sound-packs/urban-drum-samples/
var snare;
var bass;
var hihat;
var hightom;
var lowtom;

function preload() {
    snare = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/"
            + "uploads/2017/12/creyes1-snare.wav");
    snare.setVolume(.3);
    bass = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/"
           + "uploads/2017/12/creyes1-bass.wav");
    bass.setVolume(1);
    hihat = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/"
            + "uploads/2017/12/creyes1-hihat.wav");
    hihat.setVolume(.6);
    hightom = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/"
              + "wp-content/uploads/2017/12/creyes1-hightom.wav");
    hightom.setVolume(.5);
    lowtom = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/"
             + "uploads/2017/12/creyes1-lowtom.wav");
    lowtom.setVolume(.5);
}

function setup() {
    createCanvas(480, 480);
    background(softYellow);
}

function draw() {
    background(softYellow);

    //Background detail, layered circles

    noStroke();
    fill(transWhite);
    ellipse(width/2, height/2, 400, 400);

    fill(softYellow);
    ellipse(width/2, height/2, 350, 350);

    stroke(transWhite);
    noFill();
    strokeWeight(10);
    ellipse(width/2, height/2, 320, 320);

    strokeWeight(5);
    ellipse(width/2, height/2, 500, 500);

    noStroke();
    fill(transWhite);
    ellipse(width/2, height/2, 200, 200);

    //Introductory Text & Instructions
    //Disappears once user begins playing

    noStroke();
    fill(255);
    rect(introTextX-10, 420, 440, 50, 10);

    fill(100);
    textStyle(BOLD);
    textFont("Courier New", 12);
    text('Press any key 1-5, press SPACEBAR to start/stop recording your loop. '
         + 'Double-tap SPACEBAR to stop loop. (Speakers up)',
         introTextX, 430, 450, 50);

    //Starts initial counter to track actions
    if (recording == true) {
        counter++;
    }

    //If in playback, and items are in array, play on a loop
    if (recording == false & actionFrames.length > 0) {

        counter++;

        //Loops counter after hitting max
        if (counter === counterMax) {
            counter = 0;
        }

        //Plays action if counter is the same as the frame which action occurred
        var success = false;
        for (i = 0; i < actionFrames.length; i++) {
            if (counter === actionFrames[i]) {
                success = true;
                actionIndex = i;
                break;
            }
        }

        //Plays the action if counter number matches the stored frame count
        if (success == true) {
            (actions[actionIndex])();
            (actionSounds[actionIndex]).play();
        }

    }

    //Functions check if anything is in their respective arrays, then draw
    playSlideH();
    playSlideV();
    playRectSlide();
    playRingPulse();
    playDotSpray();

    //Visual feedback

    //Red dot when recording
    if (recording == true) {
        noStroke();
        fill(204, 67, 67);
        ellipse(30, 30, 10, 10);
    }

    //Playback icon if looping with actions in array
    if (recording == false & actions.length > 0) {
        noStroke();
        fill(110, 142, 105);
        triangle(25, 25, 25, 35, 35, 30);
    }

}

var recording = false;

function keyPressed() {

    //Hides intro text once user begins playing
    if (keyCode == 32 || keyCode == 49 || keyCode == 50 ||
        keyCode == 51 || keyCode == 52 || keyCode == 53) {
        introTextX = undefined;
    }

    //Toggles a loop recorder
    if (keyCode == 32 & recording == false) {
        counter = 0;
        actions = [];
        actionFrames = [];
        actionSounds = [];
        recording = true;
        print("start");
    } else if (keyCode == 32 & recording == true) {
        counterMax = counter; //Creates a cap for counter to loop
        counter = 0;
        recording = false;
        print("stop");
    }

    //Triggers an animation and sound clip on press
    //If recording, stores action, the frame that action occurred, and the sound
    //into respective arrays - actions[], actionFrames[], actionSounds[]

    //Excluding dotSpray, clears arrays on press

    //Pressing 1 sprays dots while playing a highhat clip
    if (keyCode == 49) {
        hihat.play();
        dotSpray();
        if (recording == true) {
            print('1');
            actionFrames.push(counter);
            actions.push(dotSpray);
            actionSounds.push(hihat);
        }
    }

    //Pressing 2 slides two rectangles while playing a bass drum clip
    if (keyCode == 50) {
        bass.play();
        rectSliders = [];
        rectSlide();
        if (recording == true) {
            print('2');
            actionFrames.push(counter);
            actions.push(rectSlide);
            actionSounds.push(bass);
        }
    }

    //Pressing 3 creates a scaling ring while playing a snare clip
    if (keyCode == 51) {
        snare.play();
        rings = [];
        ringPulse();
        if (recording == true) {
            print('3');
            actionFrames.push(counter);
            actions.push(ringPulse);
            actionSounds.push(snare);
        }
    }

    //Pressing 4 slides a large panel horizontally, plays a hightom clip
    if (keyCode == 52) {
        hightom.play();
        bigSliderH = [];
        bigSlideH();
        if (recording == true) {
            print('4');
            actionFrames.push(counter);
            actions.push(bigSlideH);
            actionSounds.push(hightom);
        }
    }

    //Pressing 5 slides a large panel vertically, plays a lowtom clip
    if (keyCode == 53) {
        lowtom.play();
        bigSliderV = [];
        bigSlideV();
        if (recording == true) {
            print('5');
            actionFrames.push(counter);
            actions.push(bigSlideV);
            actionSounds.push(lowtom);
        }
    }

}

/*----Dot Spray Functions-----------------------------------------------------*/
//Dots fly out from a random position

var dots = []; //For dotSpray

//Places dots into array
function dotSpray() {
    var dotOriginX = random(0, width);
    var dotOriginY = random(0, height);
    for (var i = 0; i < 10; i++) {
        dots.push(makeDot(dotOriginX, dotOriginY));
    }
}

//Creates dot object
function makeDot(inputX, inputY) {
    var dot = {x: inputX,
               y: inputY,
               stepX: random(-20, 20),
               stepY: random(-20, 20),
               color: [random(0, 255), random(0, 255), random(0, 255)],
               size: random(5, 10),
               move: dotStep,
               display: drawDot}
    return dot;
}

//Render dot
function drawDot() {
    noStroke();
    fill(this.color);
    ellipse(this.x, this.y, this.size);
}

//Moves dot
function dotStep() {
    this.x += this.stepX;
    this.y += this.stepY;
}

//If something is in the array, execute animation
function playDotSpray() {
    //Checks if anything exists inside array
    if (dots.length > 0) {
        for (var i = 0; i < dots.length; i++) {
            //Moves and renders
            dots[i].move();
            dots[i].display();

            //If dot leaves canvas, remove it from dots array
            if (dots[i].x < 0 || dots[i].x > width ||
                dots[i].y < 0 || dots[i].y > height) {
                dots.splice(i, 1);
            }
        }
    }
}
/*----------------------------------------------------------------------------*/

/*----rectSlide Functions-----------------------------------------------------*/
//Two rectangles slide vertically across the screen, direction random

var rectSliders = []; //For rectSliders

//Places slider into array
function rectSlide() {
    var startingY = 480;
    var slideRate = 20;

    var sliderY1;    //Input for the first rectangle's Y position
    var sliderStep1; //Input for the first rectangle's move speed

    var sliderY2;    //Input for the second rectangle's Y position
    var sliderStep2; //Input for the first rectangle's move speed

    //50/50 chance on which direction the sliders travel
    var coin1 = coinToss();
    if (coin1 == true) {
        sliderY1 = -startingY;
        sliderStep1 = slideRate;
    } else {
        sliderY1 = startingY;
        sliderStep1 = -slideRate;
    }

    rectSliders.push(makeSlider(100, sliderY1, sliderStep1));

    var coin2 = coinToss();
    if (coin2 == true) {
        sliderY2 = -startingY;
        sliderStep2 = slideRate;
    } else {
        sliderY2 = startingY;
        sliderStep2 = -slideRate;
    }

    rectSliders.push(makeSlider(300, sliderY2, sliderStep2));
}

//Creates slider object
function makeSlider(inputX, inputY, inputS) {
    var slider = {x: inputX,
                  y: inputY,
                  w: 150,
                  h: 480,
                  color: lightCyan,
                  stepY: inputS,
                  move: slideStep,
                  display: drawSlider};
    return slider;
}

//Renders slider
function drawSlider() {
    noStroke();
    fill(this.color);
    rect(this.x, this.y, this.w, this.h);
}

//Moves slider
function slideStep() {
    this.y += this.stepY;
}

//If something is in the array, execute animation
function playRectSlide() {
    //Checks if anything exists inside array
    if (rectSliders.length > 0) {
        for (var i = 0; i < rectSliders.length; i++) {
            rectSliders[i].move();
            rectSliders[i].display();

            //If rectangle leaves canvas, remove it from array
            if (rectSliders[i].y < -500 || rectSliders[i] > 500) {
                rectSliders.splice(i, 1);
            }
        }
    }
}
/*----ringPulse Functions-----------------------------------------------------*/
//Creates a ring that grows or shrinks in size from center
var rings = [];

//Places ring into array
function ringPulse() {
    var scaleRate = 50;
    var startingSize; //Input for ring's starting size
    var scaleTick; //Input for ring scale rate
    var coin = coinToss();

    //Determines direrction ring is scaling
    if (coin == true) {
        //Ring explodes outwards
        startingSize = 0;
        scaleTick = scaleRate;
    } else {
        //Ring collapses inwards
        startingSize = width*1.5;
        scaleTick = -scaleRate;
    }

    rings.push(makeRing(startingSize, scaleTick));

}

//Creates ring object
function makeRing(inputSize, inputStep) {
    var ring = {x: width/2,
                y: height/2,
                size: inputSize,
                step: inputStep,
                color: darkerTeal,
                weight: 50,
                scale: ringStep,
                display: drawRing};
    return ring;
}

//Renders ring
function drawRing() {
    strokeWeight(this.weight);
    stroke(this.color);
    noFill();
    ellipse(this.x, this.y, this.size);
}

//Scales ring
function ringStep() {
    this.size += this.step;
}

//If something is in the array, execute animation
function playRingPulse() {

    if (rings.length > 0) {

        //Renders and scales ring
        for (var i = 0; i < rings.length; i++) {

            rings[i].scale();
            rings[i].display();

            //If ring gets too big or too small, remove it from array
            if (rings[i].size > width*2 || rings[i].size < 0) {
                rings.splice(i, 1);
            }
        }
    }
}
/*----------------------------------------------------------------------------*/

/*----bigSlideH Functions-----------------------------------------------------*/
//Slides a big block of color horizontally across the screen
var bigSliderH = [];

//Places slider into array
function bigSlideH() {
    var startingX = 580;
    var moveRate = 50;
    var sliderHX; //Input for X position of slider
    var sliderHS; //Input for movement rate of slider
    var coin = coinToss();

    //50/50 chance of coming in from either side of canvas
    if (coin == true) {
        sliderHX = -startingX;
        sliderHS = moveRate;
    } else {
        sliderHX = startingX;
        sliderHS = -moveRate;
    }

    bigSliderH.push(makeSliderH(sliderHX, sliderHS));
}

//Creates slider object
function makeSliderH(inputX, inputS) {
    var sliderH = {x: inputX,
                   y: 0,
                   w: width+100,
                   h: height,
                   speed: inputS,
                   col: softPink,
                   move: sliderHStep,
                   display: drawSliderH};
    return sliderH;
}

//Renders slider
function drawSliderH() {
    noStroke();
    fill(this.col);
    rect(this.x, this.y, this.w, this.h);
}

//Moves slider
function sliderHStep() {
    this.x += this.speed;
}

//If something is in the array, execute animation
function playSlideH() {
    if (bigSliderH.length > 0) {
        for (var i = 0; i < bigSliderH.length; i++) {
            bigSliderH[i].display();
            bigSliderH[i].move();

            //Clear array if sliders leave canvas
            if (bigSliderH[i].x < -580 || bigSliderH[i].x > 580) {
                bigSliderH = [];
            }
        }
    }
}
/*----------------------------------------------------------------------------*/

/*----bigSlideV Functions-----------------------------------------------------*/
//Slides a big block of color horizontally across the screen
var bigSliderV = [];

//Places slider into array
function bigSlideV() {
    var startingY = 580;
    var moveRate = 50;
    var sliderVY; //Input for Y position of slider
    var sliderVS; //Input for movement rate of slider
    var coin = coinToss();

    //50/50 chance of coming in from either side of canvas
    if (coin == true) {
        sliderVY = -startingY;
        sliderVS = moveRate;
    } else {
        sliderVY = startingY;
        sliderVS = -moveRate;
    }

    bigSliderV.push(makeSliderV(sliderVY, sliderVS));

}

//Creates slider object
function makeSliderV(inputY, inputS) {
    var sliderV = {x: 0,
                   y: inputY,
                   w: width,
                   h: height + 100,
                   speed: inputS,
                   col: softViolet,
                   move: sliderVStep,
                   display: drawSliderV};
    return sliderV;
}

//Renders slider
function drawSliderV() {
    noStroke();
    fill(this.col);
    rect(this.x, this.y, this.w, this.h);
}

//Moves slider
function sliderVStep() {
    this.y += this.speed;
}

//If something is in the array, execute animation
function playSlideV() {
    if (bigSliderV.length > 0) {
        for (var i = 0; i < bigSliderV.length; i++) {
            bigSliderV[i].display();
            bigSliderV[i].move();

            //Clear array if sliders leave canvas
            if (bigSliderV[i].y < -580 || bigSliderV[i].y > 580) {
                bigSliderV = [];
            }
        }
    }
}
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
//Returns a Boolean value with a 50/50 chance
function coinToss() {
    var coin = floor(random(0, 2));
    if (coin === 0) {
        return true;
    } else {
        return false;
    }
}

DIRECTIONS: Press number keys 1-5 to play various drum sounds, hit spacebar to record your beat, then spacebar once more to play it back – double-tap spacebar to clear your loop. A red dot in the upper-left indicates that you are recording, and an arrow indicates a loop is being played. Please turn on your speakers.

This program is a reinterpretation of Patatap created by Jono Brandel and Lullatone. While I really enjoyed my experience with Patatap, I felt that it was lacking a system to create a looping beat capability seen on percussion pads or Launchpads. Because of this, I wanted to focus less on creating a complete keyboard’s worth of complex animation and moreso on creating that kind of robust looping system.

The program works by having a running frame counter once recording begins, and storing the action with its respective animation and sound, as well as the frame that it was performed into separate arrays. To loop, the counter resets, and whenever the counter number is the same as a stored frame number, the associated action is executed. For me, the biggest challenge was having all of these arrays relate to each other and keeping everything organized for a clean loop, however once I figured out the core system down, it was just a matter of adding more content in terms of possible actions.

In the future, I’d like to develop this further to have a full keyboard’s worth of sound and animation, as well as being able to perform several loops at once (likely involving storing arrays within arrays), but for now, I’m really pleased with the final result. I’ve played percussion for several years, so it was really enjoyable to get the chance to translate that interest over to a different medium.

Sounds are from Urban Drum Samples on SoundPacks.com, by user Biochron.

kyungak + dayoungl – finalproject

For our final project, Sharon and I made a game named, “TOM.” In order to play TOM, users are to:

  1. Use the arrow keys (up, down, left, right) to move the main character, TOM
  2. Avoid contact with bombs – if contact is made, TOM dies and the game is over
  3. Avoid contact with puffs – if contact is made, TOM loses a point (-1)
  4. Consume hearts – if contact is made, TOM earns a point (+1)
  5. Notice: If bombs make contact with hearts, the bomb bursts and gets rid of the hearts
  6. Notice: Hearts randomly get patched across the canvas. It shrinks in size and disappears if not consumed by TOM.
  7. Notice: When the game starts, you might immediately see the game over sign because the randomly generated bombs overlap with the initial position of TOM (100,100). Don’t panic and just refresh the webpage so you can restart.

Your goal is to get as much point as possible. Compete with friends and see who can get the most points!

Please download the file and use the local file to access the html file of TOM.

PLAY ME

GRADE ME

sketch

//Kyunga Ko
//15104B
//kyungak@andrew.cmu.edu
//Capstone Project:Tom and Toms (COMPLETE VERSION)

var bomb;
var puff;
var heart;
var explosion;
var tomcharacter; 
var eating;
var gameover;
var scoreboard;
var score = 0;

function preload() {

  //Preloading gameover and scoreboard image
  gameover = loadImage("https://i.imgur.com/VlLC4xC.png");
  scoreboard = loadImage("https://i.imgur.com/8ke3Z26.png");

}

function setup() {
  createCanvas(800,800);  

  //Grouping variables
  bomb = new Group();
  puff = new Group();
  heart = new Group();
  explosion = new Group();
  tomcharacter = new Group();
  eating = new Group();

  //Create bomb at random locations on canvas
  for(var i=0; i<15; i++) {
    createBomb(random(0,width), random(0,height));
  }

  //Single character "Tom" is created
  for(var i=0; i<1; i++) {
    createTom(100, 100);
  }

}

function draw() {
  background(230);
  //Reduce the size of the heart by the rate of the frameCount
  if(frameCount%60==0 & heart.length<5) {
    //Create hearts at random locations on the canvas
    createHeart(random(0,width), random(0,height)); 
  }
  
  //Recycle puff on four sides = randomly displaced
  if(frameCount%60==0 & puff.length<10) {
    var canvasside = floor(random(0,4));
    
    if(canvasside == 0) //left
      createPuff(0, random(height));
    if(canvasside == 1) //right
      createPuff(width, random(height));
    if(canvasside == 2) //top
      createPuff(random(width), 0);
    if(canvasside == 3) //bottom
      createPuff(random(width), height);
      
    }
  
  //(BOMB) Bomb orientation in general
  for(var i = 0; i<bomb.length; i++) {
  
    var b = bomb[i];
    b.noisePosition += 0.1;
    b.rotation += (noise(b.noisePosition)-0.5)*10;
    b.setSpeed(2, b.rotation);
    randomrelocation(b);

  }
  
  //(PUFF) When puff collides with bomb and heart
  for(var i = 0; i<puff.length; i++) {
      var p = puff[i]; 
      randomrelocation(p);

      for(var j = 0; j<bomb.length; j++) {
        var b = bomb[j]; 
        //Distance btw puff and bomb
        var dis = p5.Vector.dist(p.position, b.position); 
        
        //Puff and bomb does not attract
        if(dis < 70) {   
          var angle = degrees(atan2(b.position.y-p.position.y, 
            b.position.x-p.position.x));
          //repel
          var attraction = -30 / dis;
          p.addSpeed(attraction, angle);

        }
      }

      for(var z = 0; z<heart.length; z++) {
        var h = heart[z]; 
        //Distance btw heart and puff
        var dis2 = p5.Vector.dist(p.position, h.position); 
        
        //Puff and heart attract
        if(dis2 < 30) {   
          var angle2 = degrees(atan2(h.position.y-p.position.y, 
            h.position.x-p.position.x));
          var attraction2 = 100 / dis2;
          p.addSpeed(attraction2, angle2);

        }

      }
  }

  //(HEART) When heart collides with bomb and puff
  for(var i = 0; i<heart.length; i++) {

      var h = heart[i]; //save in a temp variable
      h.scale = map(h.life, 300, 0, 1, 0);
      h.overlap(bomb, bombeatsheart);
      h.overlap(puff, puffeatsheart); 

  }

  //(TOM) When Tom collides with bomb and heart
  for(var i = 0; i<tomcharacter.length; i++) {

    var t = tomcharacter[i]; //save in a temp variable
    t.overlap(bomb, bombmeetstom); 
    t.overlap(heart, heartmeetstom);
    t.overlap(puff, puffmeetstom);
   
  }

  //Scoreboard
  image(scoreboard, 580, 15); //Scoreboard image
  textSize(30);
  fill(0); 
  text(score,670,90); //Displays the score

  //Draws all sprites
  drawSprites();

}

//Makes Tom move up, down, left, right using the arrow keys
function keyPressed(){
  var tab = 20;
  var clickCount = 0;

  for (var i = 0; i<tomcharacter.length; i++ ){
    var t = tomcharacter[i];

    if (keyIsPressed === true){
      clickCount ++; //clickcount increases with movement
    }

    if (keyIsDown(LEFT_ARROW)){
      t.position.x -= tab; //left
    }

    if (keyIsDown(RIGHT_ARROW)){
      t.position.x += tab; //right
    }

    if (keyIsDown(UP_ARROW)){
      t.position.y -= tab; //up

    } else if (keyIsDown(DOWN_ARROW)){
      t.position.y += tab; //down
      }
    
  }
  
}

//The object dissapears outside the canvas and is randomly located again
function randomrelocation(w) {
   //wrap around the screen
    if (w.position.x > width)
      w.position.x = 0;
    if (w.position.x < 0)
      w.position.x = width;
    if (w.position.y > height)
      w.position.y = 0;
    if (w.position.y < 0)
      w.position.y = height;

}

//When puff eats the heart, they multiply x2 
function puffeatsheart(puff, heart) {
  puff.remove();
  createPuff(heart.position.x, heart.position.y);

}

//When Tom meets puff, score decreases by one
function puffmeetstom(puff, tomcharacter) {
  tomcharacter.remove();
  score--;

}

//Bomb eats/gets rid of the heart + explosion sign
function bombeatsheart(bomb, heart) {
  bomb.remove();
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  

}

//Tom eats heart and +1 sign comes up
function heartmeetstom(heart, tomcharacter) {
  tomcharacter.remove();
  aftereatingheart(heart.position.x, heart.position.y);
  score++;
  
}

//When bomb meets Tom, Tom dies and game over sign comes up
function bombmeetstom(bomb, Tom) {
  bomb.remove();
  noLoop();
  push();
  scale(0.7);
  image(gameover, 175, 400);
  pop();

}

//Bomb is created
function createBomb(x, y) {

  var b = createSprite(x, y);
  b.addAnimation("bomb", "https://i.imgur.com/N4m1kty.png");
  b.setSpeed(2, random(0,360));
  b.noisePosition = random(0, 1000);
  b.maxSpeed = 2;
  bomb.add(b);

}

//When bomb eats heart, explosion is created to indicate that a heart was ate
function createExplosion(x, y) {

  var e = createSprite(x, y);
  e.addAnimation("bomb", "https://i.imgur.com/wzVAcbK.png");
  e.setSpeed(2, random(0,360));
  e.noisePosition = random(0, 1000);
  e.maxSpeed = 2;
  explosion.add(e);

}

//After Tom eats heart, +1 sign is created
function aftereatingheart(x, y) {

  var a = createSprite(x,y);
  a.addAnimation("eat", "https://i.imgur.com/b9C1Xyl.png");
  a.setSpeed(2, random(0,360));
  a.noisePosition = random(0, 1000);
  a.maxSpeed = 2;
  eating.add(a);

}

//Puff is created
function createPuff(x, y) {

  var p = createSprite(x, y);
  p.addAnimation("puff", "https://i.imgur.com/cs8Mkcr.png");
  p.setSpeed(-2, random(0,360));
  p.maxSpeed = 1;
  puff.add(p);

}

//Heart is created
function createHeart(x, y) {
  
  var h = createSprite(x, y);
  h.addAnimation("heart", "https://i.imgur.com/u2uRAYl.png");
  h.life = 300; 
  heart.add(h);

}

//Tom is created
function createTom(x, y) {

  var t = createSprite(x, y);
  t.addAnimation("tomcharacter", "https://i.imgur.com/Q8FnPtP.png", 
    "https://i.imgur.com/QzOR227.png");
  tomcharacter.add(t);

}

















dayoungl & kyungak – Final project

Please refer to the gif file for how the game works.The objective of our game, “TOM” is to survive from the bombs by navigating its to stay away from bombs. A little bonus of the game would be eating hearts to achieve higher points. One can navigate the character using the arrow keys. The scoreboard on the top right corner keeps track of the hearts the character eats. Each time character consumes a heart, it will be logged as +1 on the scoreboard; whenever the character comes into contact with the puffs, it will result in -1 point from the scoreboard. When the character comes into contact with the bomb, the game will end with a “gameover” message. When heart and bomb collides with each other, the heart will turn into a little fire icon indicating that the heart is gone.

Download the PLAY-ME version to play the game on your device.

PLAY-ME
GRADE-ME

data-width=”800″ data-height=”800″TOM-FINAL

//Kyunga Ko
//15104B
//kyungak@andrew.cmu.edu
//Capstone Project:Tom and Toms (COMPLETE VERSION)

var bomb;
var puff;
var heart;
var explosion;
var tomcharacter; 
var eating;
var gameover;
var scoreboard;
var score = 0;

function preload() {

  //Preloading gameover and scoreboard image
  gameover = loadImage("https://i.imgur.com/VlLC4xC.png");
  scoreboard = loadImage("https://i.imgur.com/8ke3Z26.png");

}

function setup() {
  createCanvas(800,800);  

  //Grouping variables
  bomb = new Group();
  puff = new Group();
  heart = new Group();
  explosion = new Group();
  tomcharacter = new Group();
  eating = new Group();

  //Create bomb at random locations on canvas
  for(var i=0; i<15; i++) {
    createBomb(random(0,width), random(0,height));
  }

  //Single character "Tom" is created
  for(var i=0; i<1; i++) {
    createTom(100, 100);
  }

}

function draw() {
  background(230);
  //Reduce the size of the heart by the rate of the frameCount
  if(frameCount%60==0 & heart.length<5) {
    //Create hearts at random locations on the canvas
    createHeart(random(0,width), random(0,height)); 
  }
  
  //Recycle puff on four sides = randomly displaced
  if(frameCount%60==0 & puff.length<10) {
    var canvasside = floor(random(0,4));
    
    if(canvasside == 0) //left
      createPuff(0, random(height));
    if(canvasside == 1) //right
      createPuff(width, random(height));
    if(canvasside == 2) //top
      createPuff(random(width), 0);
    if(canvasside == 3) //bottom
      createPuff(random(width), height);
      
    }
  
  //(BOMB) Bomb orientation in general
  for(var i = 0; i<bomb.length; i++) {
  
    var b = bomb[i];
    b.noisePosition += 0.1;
    b.rotation += (noise(b.noisePosition)-0.5)*10;
    b.setSpeed(2, b.rotation);
    randomrelocation(b);

  }
  
  //(PUFF) When puff collides with bomb and heart
  for(var i = 0; i<puff.length; i++) {
      var p = puff[i]; 
      randomrelocation(p);

      for(var j = 0; j<bomb.length; j++) {
        var b = bomb[j]; 
        //Distance btw puff and bomb
        var dis = p5.Vector.dist(p.position, b.position); 
        
        //Puff and bomb does not attract
        if(dis < 70) {   
          var angle = degrees(atan2(b.position.y-p.position.y, 
            b.position.x-p.position.x));
          //repel
          var attraction = -30 / dis;
          p.addSpeed(attraction, angle);

        }
      }

      for(var z = 0; z<heart.length; z++) {
        var h = heart[z]; 
        //Distance btw heart and puff
        var dis2 = p5.Vector.dist(p.position, h.position); 
        
        //Puff and heart attract
        if(dis2 < 30) {   
          var angle2 = degrees(atan2(h.position.y-p.position.y, 
            h.position.x-p.position.x));
          var attraction2 = 100 / dis2;
          p.addSpeed(attraction2, angle2);

        }

      }
  }

  //(HEART) When heart collides with bomb and puff
  for(var i = 0; i<heart.length; i++) {

      var h = heart[i]; //save in a temp variable
      h.scale = map(h.life, 300, 0, 1, 0);
      h.overlap(bomb, bombeatsheart);
      h.overlap(puff, puffeatsheart); 

  }

  //(TOM) When Tom collides with bomb and heart
  for(var i = 0; i<tomcharacter.length; i++) {

    var t = tomcharacter[i]; //save in a temp variable
    t.overlap(bomb, bombmeetstom); 
    t.overlap(heart, heartmeetstom);
    t.overlap(puff, puffmeetstom);
   
  }

  //Scoreboard
  image(scoreboard, 580, 15); //Scoreboard image
  textSize(30);
  fill(0); 
  text(score,670,90); //Displays the score

  //Draws all sprites
  drawSprites();

}

//Makes Tom move up, down, left, right using the arrow keys
function keyPressed(){
  var tab = 20;
  var clickCount = 0;

  for (var i = 0; i<tomcharacter.length; i++ ){
    var t = tomcharacter[i];

    if (keyIsPressed === true){
      clickCount ++; //clickcount increases with movement
    }

    if (keyIsDown(LEFT_ARROW)){
      t.position.x -= tab; //left
    }

    if (keyIsDown(RIGHT_ARROW)){
      t.position.x += tab; //right
    }

    if (keyIsDown(UP_ARROW)){
      t.position.y -= tab; //up

    } else if (keyIsDown(DOWN_ARROW)){
      t.position.y += tab; //down
      }
    
  }
  
}

//The object dissapears outside the canvas and is randomly located again
function randomrelocation(w) {
   //wrap around the screen
    if (w.position.x > width)
      w.position.x = 0;
    if (w.position.x < 0)
      w.position.x = width;
    if (w.position.y > height)
      w.position.y = 0;
    if (w.position.y < 0)
      w.position.y = height;

}

//When puff eats the heart, they multiply x2 
function puffeatsheart(puff, heart) {
  puff.remove();
  createPuff(heart.position.x, heart.position.y);

}

//When Tom meets puff, score decreases by one
function puffmeetstom(puff, tomcharacter) {
  tomcharacter.remove();
  score--;

}

//Bomb eats/gets rid of the heart + explosion sign
function bombeatsheart(bomb, heart) {
  bomb.remove();
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  createExplosion(heart.position.x, heart.position.y);
  

}

//Tom eats heart and +1 sign comes up
function heartmeetstom(heart, tomcharacter) {
  tomcharacter.remove();
  aftereatingheart(heart.position.x, heart.position.y);
  score++;
  
}

//When bomb meets Tom, Tom dies and game over sign comes up
function bombmeetstom(bomb, Tom) {
  bomb.remove();
  noLoop();
  push();
  scale(0.7);
  image(gameover, 175, 400);
  pop();

}

//Bomb is created
function createBomb(x, y) {

  var b = createSprite(x, y);
  b.addAnimation("bomb", "https://i.imgur.com/N4m1kty.png");
  b.setSpeed(2, random(0,360));
  b.noisePosition = random(0, 1000);
  b.maxSpeed = 2;
  bomb.add(b);

}

//When bomb eats heart, explosion is created to indicate that a heart was ate
function createExplosion(x, y) {

  var e = createSprite(x, y);
  e.addAnimation("bomb", "https://i.imgur.com/wzVAcbK.png");
  e.setSpeed(2, random(0,360));
  e.noisePosition = random(0, 1000);
  e.maxSpeed = 2;
  explosion.add(e);

}

//After Tom eats heart, +1 sign is created
function aftereatingheart(x, y) {

  var a = createSprite(x,y);
  a.addAnimation("eat", "https://i.imgur.com/b9C1Xyl.png");
  a.setSpeed(2, random(0,360));
  a.noisePosition = random(0, 1000);
  a.maxSpeed = 2;
  eating.add(a);

}

//Puff is created
function createPuff(x, y) {

  var p = createSprite(x, y);
  p.addAnimation("puff", "https://i.imgur.com/cs8Mkcr.png");
  p.setSpeed(-2, random(0,360));
  p.maxSpeed = 1;
  puff.add(p);

}

//Heart is created
function createHeart(x, y) {
  
  var h = createSprite(x, y);
  h.addAnimation("heart", "https://i.imgur.com/u2uRAYl.png");
  h.life = 300; 
  heart.add(h);

}

//Tom is created
function createTom(x, y) {

  var t = createSprite(x, y);
  t.addAnimation("tomcharacter", "https://i.imgur.com/Q8FnPtP.png", 
    "https://i.imgur.com/QzOR227.png");
  tomcharacter.add(t);

}

















eeryan + yoonyouk_Final Project

sketch

// Erin Ryan and Yoon Young Kim
// eeryan@andrew.cmu.edu
// yoonyouk@andrew.cmu.edu
// Section C and Section E
//FINAL PROJECT - water animation


//HOME PAGE VARIABLES
//STARTING CODE WITH HOME PAGE
var animation = 0;
//text position variables
var textStart1 = 0;
var textStart2 = 140;
var textStart3 = 280;
var textStart4 = 420;
var textSpace = 140;

//RAINFALL ANIMATION VARIABLES
var numClicks = 0; 
var fall = false; //starting the animation off
var water = [];
var xr; //x position of water droplets

//COHESION ANIMATION VARIABLES
var move = false;
var drop1; //first water object 
var drop2; //second water object 
var opacity = 100; //variable to deal with changing opacity of fills and strokes of different water objects

//RIPPLE ANIMATION VARIABLES
var rx;
var ry;
var diam;

//SPLASH ANIMATION VARIABLES
var SPLASH = [];
var droplets = [];
var dropX = -50; //x coordinate of the water drop
var dropY = 0; // y coordinate of the water drop
var splashpoint = 150;
var numClick = 0;
var explodeTime;
var timeElapsed;
var splashed = false;

function preload(){
    var splashImgs = [];
    //img links of the splash droplets
    splashImgs[0] = "https://i.imgur.com/Aau3BBu.png";
    splashImgs[1] = "https://i.imgur.com/C156jX4.png";
    splashImgs[2] = "https://i.imgur.com/nnR9v06.png";

    //cycling images by pushing into SPLASH array
    for(var i = 0; i<3; i++){
        SPLASH.push(loadImage(splashImgs[i]));
    }
}

function setup() {
  createCanvas(400, 300);
  //object declaration for cohesion animation
  drop1 = makeDrop(120, height / 2, 100);
  drop2 = makeDrop(width - 120, height / 2,100);
  //pushes raindrop objects into the array water
  for(var i = 0; i < 300; i++){
    xr = random(0, width); 
    water.push(makeRain(xr, 20, 5, 0)); 
  }
}

function draw() {
  //default page
  if(animation === 0){ 
    background(173, 212, 255);
    textSize(20);
    fill(255, 255, 255);
    textFont("Courier New")
    text("let's play with water!", width / 2 - 130, 100);
    menuText(200);
  }
  //ripple animation
  if(animation == 1){ 
    background(238, 252, 255);
    noStroke();
    fill(80, 130, 200);
    textFont("courier", 16);
    textAlign(CENTER);
    text("click to touch the water...", width / 2, 30); // creates text guiding user to press a key
    ripple(rx, ry);
    if(diam < 550){
      diam += 1; //circle expands
      opacity -= 0.4; //circle becomes less opaque as it expands
    }
    menuText(275);
  }
  //splash animation
  else if(animation == 2){
    background(238, 252, 255);
    noStroke();
    fill(80, 130, 200);
    textFont("courier", 16);
    textAlign(CENTER);
    text("click to splash water droplets", width / 2, 30); // creates text guiding user to press a key
    fill(26, 133, 192);
    if(dropY > 0 & dropY < splashpoint){
        droplet(dropX, dropY);
        dropY++;
    }
    if(dropY == splashpoint){
        splashed = true;
        if(explodeTime == null){
          explodeTime = frameCount;  
        }
    }
    if(splashed == true){
        timeElapsed = frameCount - explodeTime;
    for(var i = 0; i < 12; i++){
        if(timeElapsed == i){
            imageMode(CENTER);
            image(SPLASH[floor(i / 4)], dropX, dropY);
            }
        }
    }
    menuText(275);
  }
  //rain code animation
  else if(animation == 3){ 
    background(238, 252, 255);
    fill(80, 130, 200);
    textFont("courier", 16);
    textAlign(CENTER);
    text("click once for to make it rain...", width / 2, 30); // creates text guiding user to press a key
    text("click again for clear skies", width / 2, 55);
    if(fall){ 
      for(var i = 0; i < water.length; i++){
        water[i].render();
        water[i].fall();
      }
    }
    menuText(275);
  }
  //cohesion animation
  else if(animation == 4){ 
    background(238, 252, 255);
    textAlign(CENTER);
    noStroke();
    fill(80, 180, 200);
    textFont("courier", 16);
    text("click to see cohesion...", width / 2, 30);
    drop1.render();
    drop2.render();
    if(dist(drop1.x, drop1.y, drop2.x, drop2.y) > 0 & move){// if the two objects are not on top of each other and move == true
      drop1.x++;                                            // move the two drops towards each other and lessen the opacity of their strokes
      drop2.x--;
      opacity -= 1.3;
    }
    menuText(275);
  }
}
    
function keyTyped(){ // assigns a different value to the variable animation based on the key pressed
    if (key == 'r'){ 
      animation = 1;
    }
    if (key == 's'){ 
      animation = 2;
    } 
    if (key == 'u'){ 
      animation = 3;
    }                                             
    if (key == 'c'){ 
      animation = 4;
    } 
    
}

function menuText(posY){ //makes menu scroll with instructions
    noStroke();
    fill(80, 130, 200);
    textSize(10);
    text("press R for ripples", textStart1, posY);
    text("press S for splash", textStart2, posY);
    text("press U for rain", textStart3, posY);
    text("press C for cohesion", textStart4, posY);
    textStart1++;
    textStart2++;
    textStart3++;
    textStart4++;
    if(textStart1 > width){
        textStart1 = -140;
    }    
    if(textStart2 > width){
        textStart2 = -140;
    }
    if(textStart3 > width){
        textStart3 = -140;
    }
    if(textStart4 > width){
        textStart4 = -140;
    }
}

function mousePressed(){
  //variable reset for ripple code
  diam = 0;
  opacity = 100;
  rx = mouseX;
  ry = mouseY;
  if(animation == 2){
    numClick++;
    dropX = mouseX;
    dropY = 1;
    splashpoint = mouseY;
  }

  //rain
  if(animation == 3){
    numClicks++;
    if(numClicks%2 == 1){
      fall = true;
    }
    else{
      fall = false;
    }
  }

  //cohesion
  if(animation == 4){
    move = true;
  }
}

function ripple(px, py){ //draws ripples
  noFill();
  strokeWeight(2.5);
  stroke(0, 0, 255, opacity);
  ellipse(px, py, diam, diam);
  strokeWeight(2);
  ellipse(px, py, diam / 2, diam / 2);
  strokeWeight(1.5);
  ellipse(px, py, diam / 4, diam / 4);
}

function droplet(x, y){
  fill(26, 133, 192);
  //using the map function in order to expand the drop as it moves down
  var xmap = map(dropY, 0, height, 5, 15);
  var ymap = map(dropY, 0, height, 10, 30);
  noStroke();
  beginShape();
  curveVertex(x, y);
  curveVertex(x, y);
  curveVertex(x - xmap, y + ymap);
  curveVertex(x, y + ymap + xmap);
  curveVertex(x + xmap, y + ymap);
  curveVertex(x, y);
  curveVertex(x, y);
  endShape();    
}

//object implementation for cohesion animation
function drawDrop(){ //draws water drop for cohesion animation
  stroke(80, 130, 200, opacity);
  strokeWeight(3);
  fill(230, 242, 255);
  ellipse(this.x, this.y, this.w, this.w);
  noStroke();
}

function makeDrop(posX, posY, diam){//make water drop object for cohestion animation
  var drop = {x:posX, y:posY, w:diam, render:drawDrop};
  return drop;
}

//object implementation for rain animation
function makeRain(px, py, diam, velocity){ //make rain object
  var raindrop = {x:px, y:py, d:diam, v:velocity, render: drawRain, fall:rainFall};
  return raindrop;
}

//draws raindrop
function drawRain(){
  noStroke();
  fill(0, 10, 150, 60);
  ellipse(this.x, this.y, this.d, this.d);
  triangle(this.x - (this.d)/2, this.y, this.x, this.y - 5, this.x + (this.d)/2, this.y);
}

function rainFall(){
  this.v = random(0,8); //randomizess velocity variable
  this.y += this.v; //adds velocity to current y value of each rain drop objects so they'll fal at different speeds
  if(this.y >= height){ //resets rain drops to the top once it hits the bottom of the page
    this.y = 0;
  }
}

For this project, I collaborated with Erin Ryan from Lab section C to make a series of four water-based animations using different animation, interactive, and object oriented techniques. We coded the four interactive animations and the home screen separately, then used a series of conditionals to allow the user to toggle between different animations. We tried to establish cohesive visual language through use of color and simple shapes.

 

Initial sketches of water animations

mecha-alchan-final-project

Use the number keys in order to progress in the story!

sketch

var playerChoices = [];
var currentScene = 0;
var sceneList = [];

var leggyFish = [];
var leggyFishLoad = [];

var cat = [];
var catLoad = [];

var catFamily = [];
var catFamilyLoad = [];

var possums = [];
var possumsLoad = [];

var backgrounds = [];
var backgroundsLoad = [];

var endingImages = [];
var endingImagesLoad = [];

var items = [];
var itemsLoad = [];

function preload(){
    //preloads images for background, characters, items, etc.
    //imgur file link https://imgur.com/a/I9BTC

    //backgrounds
    //home
    backgrounds[0] = "https://i.imgur.com/fdhG0uX.png";
    //store
    backgrounds[1] = "https://i.imgur.com/XLXhiQ1.png";
    //street
    backgrounds[2] = "https://i.imgur.com/C9gVejq.png";
    //possum ending
    backgrounds[3] = "https://i.imgur.com/hoVazkD.png";
    //lose ending
    backgrounds[4] = "https://i.imgur.com/Dyp8s1Z.png";

    //characters
    //cat neutral
    cat[0] = "https://i.imgur.com/3edcYR9.png";
    //cat sad
    cat[1] = "https://i.imgur.com/u1bIhz2.png";
    //cat happy
    cat[2] = "https://i.imgur.com/YFuQ8tH.png";

    //cat family neutral
    catFamily[0] = "https://i.imgur.com/iWE061b.png";
    //cat family angry
    catFamily[1] = "https://i.imgur.com/dwXS352.png";
    //cat family happy
    catFamily[2] = "https://i.imgur.com/gJDwiOw.png";
    //cat full family
    catFamily[3] = "https://i.imgur.com/qJ2XmCm.png";

    //leggy fish neutral
    leggyFish[0] = "https://i.imgur.com/afO8XhG.png";
    //leggy fish sad
    leggyFish[1] = "https://i.imgur.com/h90qSVH.png";
    //leggy fish happy
    leggyFish[2] = "https://i.imgur.com/kSy0YDp.png";

    //possums neutral
    possums[0] = "https://i.imgur.com/BV6DYd7.png";
    //possums mad
    possums[1] = "https://i.imgur.com/2EGHdrk.png";

    //water ending
    endingImages[0] = "https://i.imgur.com/QwObsf3.png";
    //milk ending
    endingImages[1] = "https://i.imgur.com/NO4hAnK.png";
    //bad possum ending
    endingImages[2] = "https://i.imgur.com/smECEKi.png";
    //good possum ending
    endingImages[3] = "https://i.imgur.com/EX8XQjv.png";
    //bad cat ending
    endingImages[4] = "https://i.imgur.com/mjmR2QE.png";
    //good cat ending
    endingImages[5] = "https://i.imgur.com/Xj8lU3S.png";
    //leggy fish ending
    endingImages[6] = "https://i.imgur.com/ni1ZpWr.png";

    //knock off oreos image
    items[0] = "https://i.imgur.com/0RvrPHJ.png";
    //fish
    items[1] = "https://i.imgur.com/cIw1WkF.png";
    //grocery store PANTS
    items[2] = "https://i.imgur.com/bRV6gGk.png";
    //milk
    items[3] = "https://i.imgur.com/Psx2phG.png";

    // load all images and add to appropriate arrays
    for(var b = 0; b < backgrounds.length; b++){
        backgroundsLoad[b] = loadImage(backgrounds[b]);
    }
    for(var c = 0; c < cat.length; c++){
        catLoad[c] = loadImage(cat[c]);
    }
    for(var cF = 0; cF < catFamily.length; cF++){
        catFamilyLoad[cF] = loadImage(catFamily[cF]);
    }
    for(var l = 0; l < leggyFish.length; l++){
        leggyFishLoad[l] = loadImage(leggyFish[l]);
    }

    for(var p = 0; p < possums.length; p++){
        possumsLoad[p] = loadImage(possums[p]);
    }

    for(var e = 0; e < endingImages.length; e++){
        endingImagesLoad[e] = loadImage(endingImages[e]);
    }

    for(var i = 0; i < items.length; i++){
        itemsLoad[i] = loadImage(items[i]);
    }
}

function createScenes() {
    // create all scenes & choices and add them to an array
    // format: main dialogue, choice 1 text, choice 1 next scene #,
    //         choice 2 text, choice 2 next scene #,
    //         choice 3 text (or "none"), choice 3 next scene,
    //         background image, character image
    // should set up a spreadsheet to keep track of scene nums

    //scenes at home
    sceneList.push(makeScene("you wake up", "time for cereal", 1,
    "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));
    sceneList.push(makeScene("oh no! you're out of milk", "go to store", 4,
    "water's basically the same thing", 2, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));

    //ENDING 1
    sceneList.push(makeScene("this cereal is reacting strangely to water...","BOOM!!!",3,"none",0,"none",0,backgroundsLoad[0], backgroundsLoad[0]));
    sceneList.push(makeScene("your cereal spontaneously combusted", "none", 0, "none", 0, "none", 0, backgroundsLoad[0],backgroundsLoad[0]));

    //store scenes
    sceneList.push(makeScene("the sun is shining as you walk down the street", "head to the store", 5, "none", 0, "none", 0, backgroundsLoad[2], backgroundsLoad[2]))
    sceneList.push(makeScene("you're here for milk, but you're tempted to pick something else up", "resist the temptation", 6,
    "wander the aisles", 9, "none", 0, backgroundsLoad[1], backgroundsLoad[1]));
    sceneList.push(makeScene("you're on a mission", "take your milk home", 7, "actually, wait...", 9, "none", 0, backgroundsLoad[1], backgroundsLoad[1]));

    //ENDING 2
    sceneList.push(makeScene("you eat your cereal", "wow, you're so boring", 8, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));
    sceneList.push(makeScene("technically you win, but you are a loser", "none", 0, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));

    sceneList.push(makeScene("you head to the...", "junk food aisle", 10, "seafood section", 11, "dairy section", 6, backgroundsLoad[1], backgroundsLoad[1]));
    sceneList.push(makeScene("you do love your sweets", "let's get some roreos", 13, "aren't you on a diet", 9, "wait what's that", 12, backgroundsLoad[1], backgroundsLoad[1]));
    sceneList.push(makeScene("the fish are so fresh", "why not?", 25, "you don't even like seafood", 9, "none", 0, backgroundsLoad[1], backgroundsLoad[1]));
    sceneList.push(makeScene("are those........ pants", "grocery store pants oh heck yeah", 42, "you don't trust no grocery store pants", 9, "none", 0, backgroundsLoad[1], backgroundsLoad[1]));
    sceneList.push(makeScene("you have just enough money", "time to go home", 14, "none", 0, "none", 0, backgroundsLoad[1], backgroundsLoad[1]));

    //possum scenes
    sceneList.push(makeScene("you stroll down the street", "what's that?", 15, "none", 0, "none", 0, backgroundsLoad[2], backgroundsLoad[2]));
    sceneList.push(makeScene("something emerges from a trah can", "say hi to the... possums?", 16, "none", 0, "none", 0, backgroundsLoad[2], possumsLoad[0]));
    sceneList.push(makeScene("the possums eye your purchase", "excuse YOU, these are mine", 17, "offer a cookie", 20, "none", 0, backgroundsLoad[2], possumsLoad[0]));
    sceneList.push(makeScene("the possums watch disapprovingly as you walk down the street", "whatever, time for cookies", 18, "none", 0, "none", 0, backgroundsLoad[2], possumsLoad[1]));

    //ENDING 3
    sceneList.push(makeScene("every bite of cookie tastes like regret", "the possums have cursed you", 19, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));
    sceneList.push(makeScene("death is coming for you", "none", 0, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));

    sceneList.push(makeScene("the possum grabs the entire package out of your hands and vanishes", "oh well", 21, "none", 0, "none", 0, backgroundsLoad[2], possumsLoad[0]));
    sceneList.push(makeScene("you unlock the door with no cookies or milk", "you hear strange rustling sounds", 22, "none", 0, "none", 0, backgroundsLoad[2], backgroundsLoad[2]));
    sceneList.push(makeScene("there's an army of possums in your house", "welcome your new family", 23, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[3]));

    //ENDING 4
    sceneList.push(makeScene("they push forward a gallon of milk", "you did the right thing", 24, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[3]));
    sceneList.push(makeScene("the possums are in the house", "none", 0, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[3]));

    //cat scenes
    sceneList.push(makeScene("you have just enough money", "time to go home", 26, "none", 0, "none", 0, backgroundsLoad[1], backgroundsLoad[1]));
    sceneList.push(makeScene("you stroll down the street", "something scurries by", 27, "none", 0, "none", 0, backgroundsLoad[2], backgroundsLoad[2]));
    sceneList.push(makeScene("a scrawny cat begs for help", "you coldly walk on", 28, "aw, he looks hungry", 34, "none", 0, backgroundsLoad[2], catLoad[1]));
    sceneList.push(makeScene("you are heartless, but not fishless", "continue on your way", 29, "none", 0, "none", 0, backgroundsLoad[2], backgroundsLoad[2]));
    sceneList.push(makeScene("as you round the corner, you hear more meows", "it's a family of cats", 30, "none", 0, "none", 0, backgroundsLoad[2], catFamilyLoad[0]));
    sceneList.push(makeScene("you stare at each other", "suddenly, one speaks", 31, "none", 0, "none", 0, backgroundsLoad[2], catFamilyLoad[0]));
    sceneList.push(makeScene("where's father? he was supposed to bring us food", "uh oh...", 32, "none", 0, "none", 0, backgroundsLoad[2], catFamilyLoad[0]));

    //ENDING 5
    sceneList.push(makeScene("you remember the cat from before", "should have given him the fish", 33, "prepare to be eaten", 33, "none", 0, backgroundsLoad[2], catFamilyLoad[1]));
    sceneList.push(makeScene("you become cat food", "none", 0, "none", 0, "none", 0, backgroundsLoad[2], catFamilyLoad[1]));

    sceneList.push(makeScene("the cat politely takes the fish", "farewell sir", 35, "none", 0, "none", 0, backgroundsLoad[2], catLoad[0]));
    sceneList.push(makeScene("as you round the corner, you hear more meows", "it's a family of cats", 36, "none", 0, "none", 0, backgroundsLoad[2], catFamilyLoad[0]));
    sceneList.push(makeScene("you smile at them", "the cat from before appears!", 37, "none", 0, "none", 0, backgroundsLoad[2], catFamilyLoad[3]));
    sceneList.push(makeScene("he gives the fish to his family", "you swear you hear them say ''thanks'' to you", 38, "none", 0, "none", 0, backgroundsLoad[2], catFamilyLoad[3]));
    sceneList.push(makeScene("that was nice", "time to go home, finally", 39, "none", 0, "none", 0, backgroundsLoad[2], backgroundsLoad[2]));
    sceneList.push(makeScene("when you get home, there's a package at your door", "there's a paw print on it", 40, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));

    //ENDING 6
    sceneList.push(makeScene("it's... a gallon of milk", "you tearfully thank the cats", 41, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));
    sceneList.push(makeScene("you have been blessed by cats", "none", 0, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));

    //leggy fish
    sceneList.push(makeScene("you have just enough money", "time to go home", 43, "none", 0, "none", 0, backgroundsLoad[1], backgroundsLoad[1]));
    sceneList.push(makeScene("you stroll down the street", "there's something odd over there", 44, "none", 0, "none", 0, backgroundsLoad[2], backgroundsLoad[2]));
    sceneList.push(makeScene("a fish head peaks at you from behind a bush", "why does this fish has legs", 45, "none", 0, "none", 0, backgroundsLoad[2], leggyFishLoad[0]));
    sceneList.push(makeScene("you should really get to know your neighbors", "...some other time", 46, "he looks sad and cold", 47, "none", 0, backgroundsLoad[2], leggyFishLoad[1]));
    sceneList.push(makeScene("what are you, heartless", "those pants won't fit you anyways", 47, "none", 0, "none", 0, backgroundsLoad[2], leggyFishLoad[1]));
    sceneList.push(makeScene("you look at your grocery store pants", "give the fish pants", 48, "give the fish pants", 48, "GIVE THE FISH PANTS", 48, backgroundsLoad[2], leggyFishLoad[1]));
    sceneList.push(makeScene("the fish hurriedly puts them on", "leggy fish looks quite dapper in those pants", 49, "none", 0, "none", 0, backgroundsLoad[2], leggyFishLoad[2]));
    sceneList.push(makeScene("you wave good bye", "leggy fish signals you to wait", 50, "none", 0, "none", 0, backgroundsLoad[2], leggyFishLoad[2]));
    sceneList.push(makeScene("the fish pulls a box from behind the bush", "thank you?", 51, "none", 0, "none", 0, backgroundsLoad[2], leggyFishLoad[2]));
    sceneList.push(makeScene("you head home with the box", "let's see what's inside", 52, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));

    //ENDING 7
    sceneList.push(makeScene("it's a gallon of milk", "wow, you have such nice neighbors", 53, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));
    sceneList.push(makeScene("this is the true ending", "none", 0, "none", 0, "none", 0, backgroundsLoad[0], backgroundsLoad[0]));
}

function setup() {
    createCanvas(480, 360);
    createScenes();
}

function draw() {
    // render the current scene
    sceneList[currentScene].draw();
}

function keyPressed() {
    var sceneToChange;
    // check which key is pressed
    // & switch to the correct scene depending on the current scene
    if(key == 1) {
        sceneToChange = sceneList[currentScene].next1;
        currentScene = sceneToChange;
    } else if(key == 2 & sceneList[currentScene].opt2 != "none") {
        sceneToChange = sceneList[currentScene].next2;
        currentScene = sceneToChange;
    }
    // make sure this is a 3rd option
    else if(key == 3 & sceneList[currentScene].opt3 != "none") {
        sceneToChange = sceneList[currentScene].next3;
        currentScene = sceneToChange;
    }
}

function drawScene() {
    // draw background image
    image(this.bg,0,0,480,360);

    // draw character or item
    image(this.character,0,0,480,360);

    // text underlay
    fill(250, 250, 250, 200);
    noStroke();
    rect(0, (2/3)*height, width,(1/3)*height);

    // draw ending text
    if(currentScene == 3 || currentScene == 8 || currentScene == 19 || currentScene == 24 || currentScene == 33 || currentScene == 41 || currentScene == 53){
        textAlign(CENTER);
        image(backgroundsLoad[4],0,0);
        fill(255);
        text("press '1' to play again ", width/2, 290);
    }
    else{
        fill(0);
    }

    //adds items
    if(currentScene == 12){
        image(itemsLoad[2],0,0);
    }
    if(currentScene == 10){
        image(itemsLoad[0],0,0);
    }
    if(currentScene == 11){
        image(itemsLoad[1], 0, 0);
    }
    if(currentScene == 6 || currentScene == 40 || currentScene == 52 || currentScene == 23){
        image(itemsLoad[3],0,0);
    }

    //adds ending images
    if(currentScene == 3){
        image(endingImagesLoad[0],0,0);
    }
    if(currentScene == 8){
        image(endingImagesLoad[1],0,0);
    }
    if(currentScene == 19){
        image(endingImagesLoad[2],0,0);
    }
    if(currentScene == 24){
        image(endingImagesLoad[3],0,0);
    }
    if(currentScene == 33){
        image(endingImagesLoad[4],0,0)
    }
    if(currentScene == 41){
        image(endingImagesLoad[5],0,0);
    }
    if(currentScene == 53){
        image(endingImagesLoad[6],0,0);
    }
    // draw main dialogue
    textAlign(CENTER);
    textStyle(NORMAL);
    textFont("Courier", 12);
    text(this.dialogue, width/2, 260);

    // draw options
    textAlign(LEFT);
    textStyle(ITALIC);
    // check if each option exists before drawing it
    if(this.opt1 != "none"){
        text("1. " + this.opt1, width/2-150, 290);
    }
    if(this.opt2 != "none") {
        text("2. " + this.opt2, width/2-150, 310);
    }
    if(this.opt3 != "none") {
        text("3. " + this.opt3, width/2-150, 330);
    }
}

// create a scene object
function makeScene(words, one, n1, two, n2, three, n3, b, c) {
    var scene = {dialogue: words,
        opt1: one,
        next1: n1,
        opt2: two,
        next2: n2,
        opt3: three,
        next3: n3,
        bg: b,
        character: c,
        draw: drawScene}
        return scene;
    }

For this project, I collaborated with Allissa Chan in order to create a choice-based game revolving around a trip to the grocery store. We used objects in order to implement all of the scenes, and created our graphics using Adobe Photoshop. There are seven different routes/endings within the game (including our definition of a “true” ending).