Sound Test

Sound Test

type 1 2 3 4 to sketch to play sounds

playfour

var one, two, three, four;


function preload() {
    one = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/one.wav");
    two = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/two.wav");
    three = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/three.wav");
    four = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/four.wav");
}


function setup() {
    createCanvas(200, 200);
    background(200);
}

function keyPressed() {
    print("" + keyCode);
    if (keyCode == 49) one.play();
    else if (keyCode == 50) two.play();
    else if (keyCode == 51) three.play();
    else if (keyCode == 52) four.play();

}

hdw/tlai – Final Project

https://helenxwu.github.io/ –> link to game

https://drive.google.com/a/andrew.cmu.edu/file/d/1NQmUsm_kBniAq7vku2QIYw7QzBkgUOP_/view?usp=sharing –> link to zip file

How to run zip:
1) download file
2) move to desktop
3) open zip folder

4) On mac– open terminal (command+space and search “terminal”)

5) type in “python -m SimpleHTTPServer 8000”

6) go to browser–type in localhost:8000 where the URL would usually go

7) find desktop listing and click on it
8) find downloaded folder and click on it
9) file will load! 🙂

For our final project, Tiffany and I made a dance dance revolution game to the Mii remix. We delved into an entirely new library (the p5js sound extension) and learned a lot about different techniques for signal processing. For the main sound visualizer, we used Fast Fourier Transform algorithm (FFT) to sample the music files’ signals over a period of time, and divided its frequency components to create the bouncing colors that react and move according to note and rhythm.

Additionally, we mapped the volume controls to create new objects under an object function, to randomly generate 4 different types of arrows. We then set a range for the function to work under so the score counter could add points. We also created a start screen and end screen for the game under two separate functions.

Sheenu-Final Project

Because it can’t be viewed properly on WordPress, please download the file.

I was always fascinated in animation ever since I was little and I always wanted to create something that would help introduce people to making animations. I made this so anyone at any age can know or get the idea and possibly get inspired.

SAMPLE:

Instructions:

  1. Adjust your character to your preferred position. Please move the character slowly.
  2. Save the frame
  3. Adjust your character very slightly little by little and save the frame every time
  4. You can view your animation forward and backward by pressing and holding one of the arrow buttons.

sketch
FinalProject-DOWNLOAD

//Sheenu You
//Section E
//sheenuy@andrew.cmu.edu; 
//Final Project

//Initial X and Y coordinates for the Ragdoll Bodyparts 
var charx = 640;
var chary = 380;
var hedx = 640;
var hedy = 220;
var arlx = 640 - 160;
var arly = 380;
var arrx = 640 + 160;
var arry = 380;
var brlx = 640 - 80;
var brly = 650;
var brrx = 640 + 80;
var brry = 650;

//Arrays that register all the X Y coordinates of all the bodyparts
var xb = [];
var yb = [];
var xh = [];
var yh = [];
var xal = [];
var yal = [];
var xar = [];
var yar = [];
var xbl = [];
var ybl = [];
var xbr = [];
var ybr = [];

//Variables that track animation frames
var frameNumber = -1;
var frames = 0;

//Variables that test if functions are running. 
var initialized = 0;
var forward = 0;
var backward = 0;

function setup() {
    createCanvas(1280, 720);
    background(220);
    frameRate(24);
}

function draw() {
    noStroke();
	
    //Controls drawing of buttons
    var playing = 0;
    var blockyMath = 100;
    var distance = 150;

    background(255, 245, 195);

    body();

    fill(124, 120, 106);
    textSize(20);
    text("FRAMES: " + frames, 5, 20);

    //Draws NewFrame Button
    fill(252, 223, 135);
    rect(width/2 - 10, 80 + 10, 180, 100);
    fill(141, 205, 193);
    rect(width/2, 80, 180, 100);
	
    //Draws Play/Stop Button
    fill(252, 223, 135);
    rect((width/2) - distance - 10, 80 + 10, blockyMath, blockyMath);
    fill(235, 110, 68);
    rect((width/2) - distance, 80, blockyMath, blockyMath);
	
    //Fills triangle if one frame is made 
    if (frames >= 1){
        fill(255);
	} else { 
        fill(231, 80, 29);
	}
    triangle((width/2) - distance + 40, 40, (width/2) - distance + 40, 120, (width/2) - distance - 40, 80);
    push();
        fill(255);
        textSize(30);
        text("ADD", 610, 75);
        text("FRAME", 590, 110);
    pop();
	
	//Draws Rewind/Stop Button
    fill(252, 223, 135);
    rect((width/2) + distance - 10, 80 + 10, blockyMath, blockyMath);
    fill(211, 227, 151);
    rect((width/2) + distance, 80, blockyMath, blockyMath);
    if (frames >= 1){
        fill(255);
    } else { 
        fill(182, 204, 104);
    }
    triangle((width/2) + distance - 40, 40, (width/2) + distance - 40, 120, (width/2) + distance + 40, 80);
	
	//PLAY/Stop Button Functions-Cycles forward through frames if mouse is pressing the button 
    if (mouseX >= ((width/2) + distance - blockyMath/2) & mouseX <= ((width/2) + 
        distance + blockyMath/2) && mouseY >= 30 && mouseY <= 135 && mouseIsPressed && frames >= 1){
        frameNumber += 1
		//Cycles through all arrays
        charx = xb[frameNumber];
        chary = yb[frameNumber];

        hedx = xh[frameNumber];
        hedy = yh[frameNumber];

        arlx = xal[frameNumber];
        arly = yal[frameNumber];

        arrx = xar[frameNumber];
        arry = yar[frameNumber];

        brlx = xbl[frameNumber];
        brly = ybl[frameNumber];

        brrx = xbr[frameNumber];
        brry = ybr[frameNumber];

        playing = 1;
        initialized = 1;
        forward = 1;
		//Goes back to latest frame when mouse is released.
    } else if (forward == 1){
        frameNumber =xb.length - 1
        playing = 0;
        initialized = 0;
        forward = 0;
    }

	//REWIND/Stop Button Functions-Cycles backward through frames if mouse is pressing the button 
    if (mouseX >= ((width/2) - distance - blockyMath/2) & mouseX <= ((width/2) - distance + 
        blockyMath/2) && mouseY >= 30 && mouseY <= 135 && mouseIsPressed && frames >= 1){
        frameNumber -= 1;
		//Cycles through all arrays
        charx = xb[frameNumber];
        chary = yb[frameNumber];

        hedx = xh[frameNumber];
        hedy = yh[frameNumber];

        arlx = xal[frameNumber];
        arly = yal[frameNumber];

        arrx = xar[frameNumber];
        arry = yar[frameNumber];

        brlx = xbl[frameNumber];
        brly = ybl[frameNumber];

        brrx = xbr[frameNumber];
        brry = ybr[frameNumber];
        initialized = 1;
        playing = 1;
        backward = 1;
		//Goes back to latest frame when mouse is released.
    } else if (backward == 1){
        frameNumber = xb.length - 1
        playing = 0;
        initialized = 0;
        backward = 0;
    }

	//Allows frames to loop when animation is going forward
    if (frameNumber >= xb.length - 1 & playing == 1 && forward == 1){
        frameNumber = -1;
    }
	//Allows frame to loop when animation is going backward
    if (frameNumber <= 0 & backward == 1 && playing == 1){
        frameNumber = xb.length;
    }

}

//Draws Ragdoll 
function body(){
	
	//Shadow
    fill(252, 223, 135);
    ellipse(charx, 670, (chary/2) + 100, 30);
	
	//Ligaments
    //Neck
    push();
    stroke(249, 213, 151);
    strokeWeight(30);
    line(charx, chary - 80, hedx, hedy);
    stroke(190, 228, 171);
    
    //ArmLeft
    line(charx, chary - 80, arlx, arly);
    
    //ArmRight
    line(charx, chary - 80, arrx, arry);
    stroke(88, 203, 172);
    
    //FootLeft
    line(charx - 20, chary + 70, brlx, brly);
   
    //FootRight
    line(charx + 20, chary + 70, brrx, brry);
    pop();

    noStroke();
    rectMode(CENTER);
    
    //Head 
    fill(249, 213, 151);
    ellipse(hedx, hedy, 100, 100);
    fill(80);
    ellipse(hedx - 10, hedy - 10, 10, 20);
    ellipse(hedx + 10, hedy - 10, 10, 20);
    ellipse(hedx, hedy + 20, 30, 30);
    fill(249, 213, 151);
    ellipse(hedx, hedy + 15, 30, 30);
   
    //Left Arm
    fill(249, 213, 151);
    ellipse(arlx, arly, 50, 50);
  
    //Right Arm
    fill(249, 213, 151);
    ellipse(arrx, arry, 50, 50);
 
    //Left Foot
    fill(112, 47, 53);
    rect(brlx, brly, 50, 50);
  
    //Right Foot
    fill(112, 47, 53);
    rect(brrx, brry, 50, 50);
   
     //Character
    fill(190, 228, 171);
    rect(charx, chary, 100, 200);
    fill(88, 203, 172);
    rect(charx, chary + 50, 100, 100);
    fill(88, 203, 172);
    rect(charx + 30, chary - 50, 20, 100);
    rect(charx - 30, chary - 50, 20, 100);

    //MouseDrag Body
    if (mouseX >= charx - 50 & mouseX <= charx + 50 && mouseY >= chary - 100 && mouseY <= chary + 100 && mouseIsPressed){
        charx = mouseX;
        chary = mouseY;
    }
    //MouseDrag Head
    if (mouseX >= hedx - 50 & mouseX <= hedx + 50 && mouseY >= hedy - 50 && mouseY <= hedy + 50 && mouseIsPressed){
        hedx = mouseX;
        hedy = mouseY;
    } 
    //MouseDrag Left Arm
    if (mouseX >= arlx - 25 & mouseX <= arlx + 25 && mouseY >= arly - 25 && mouseY <= arly + 25&& mouseIsPressed){
        arlx = mouseX;
        arly = mouseY;
    }
    //MouseDrag Right Arm
    if (mouseX >= arrx - 25 & mouseX <= arrx + 25 && mouseY >= arry - 25 && mouseY <= arry + 25 && mouseIsPressed){
        arrx = mouseX;
        arry = mouseY;
    }
    //MouseDrag Left Foot
    if (mouseX >= brlx - 25 & mouseX <= brlx + 25 && mouseY >= brly - 25 && mouseY <= brly + 25 && mouseIsPressed){
        brlx = mouseX;
        brly = mouseY;
    }
    //MouseDrag Right Foot
    if (mouseX >= brrx - 25 & mouseX <= brrx +25 && mouseY >= brry - 25 && mouseY <= brry + 25 && mouseIsPressed){
        brrx = mouseX;
        brry = mouseY;
    }

}
function mousePressed(){
	//Register/records character coordinates to new frame when "New Frame" button is pressed
    if (mouseX >= (width/2) - 90 & mouseX <= (width/2) + 90 && mouseY >= 30 && mouseY <= 135 && mouseIsPressed){
    frameNumber += 1
    frames += 1
	
	//Push character coordinates to x y arrays.
    xb.push(charx);
    yb.push(chary);

    xh.push(hedx);
    yh.push(hedy);

    xal.push(arlx);
    yal.push(arly);

    xar.push(arrx);
    yar.push(arry);

    xbl.push(brlx);
    ybl.push(brly);

    xbr.push(brrx);
    ybr.push(brry);

	//Flash
    background(255, 0, 0, 90);
	}

}
//Resets all body parts to x y coordinates of last frame created when mouse is released
//and cycling is over. 
function mouseReleased(){
    if (initialized == 1){
        charx = xb[xb.length - 1];
        chary = yb[yb.length - 1];

        hedx = xh[xh.length - 1];
        hedy = yh[yh.length - 1];
 
        arlx = xal[xal.length - 1];
        arly = yal[yal.length - 1];

        arrx = xar[xar.length - 1];
        arry = yar[yar.length - 1];

        brlx = xbl[xbl.length - 1];
        brly = ybl[ybl.length - 1];

        brrx = xbr[xbr.length - 1];
        brry = ybr[ybr.length - 1];
    }
}

Because it can’t be viewed properly on WordPress, please download the file.

 

ssharada-final-project-section-a

sketch

https://alpha.editor.p5js.org/shariwa/sketches/H16PfJF-G

Since this code has sounds, the WordPress account doesn’t display it properly. Above is a link to the p5.js alpha editor where you can properly view my code. Once at the website click the play button on the top left corner of the screen

My project looked at combining motion graphics and sounds. I wanted the graphics to work such that more was revealed as you moved around the canvas – everything is made out of two colours so as the mouse moves in the horizontal direction, you get to view more of the graphics as a differentiation is created between the background and the actual graphics.

I had an issue with running the local server on my laptop so I used the oscillation program from p5.js to get a sine curve amplitude and frequency to create a sound that my motion graphics responded to. The larger objects respond to the sound that is generated. The rippling, striped circle responds to the silence in between the beep noises. The white ellipse curve is its own thing that just renders what a traditional sine curve looks like.

When the canvas is clicked on, the noise stops and the motion graphics continue. To restart the noise you have to refresh the page.


^mouseX at at 0


^mouseX at maximum width

hannahk2-Final Project

Instructions to run the file:

1)Download and unzip the file below

spider

2) run a local server and access the file this way (it will not work otherwise unless you download the p5 editor and open it using the play button)

3) wait about 2 minutes before clicking the game to start. There are a lot of graphics so it takes a really long time to load so I would just keep clicking around the top of the screen after about 2 minutes until it loads and lets you play

4)refresh the page to restart if u lose and enjoy! Also don’t come too close to the edges of the screen.

Here is the embedded code just in case:

sketch

//Hannah Kim
//Section A
//hannahk2@andrew.cmu.edu
//Final Project

//variable for background image
var bg;
//variable for rain particles
var particles;
//variable for portal
var portalSprite;
//variable for random portal x position
var ran1;
//variable for random portal y position
var ran2;
//variable for spiders group
var spiders;

//arrays within array storing specific positions 
//of spiders on top of lillypads
var spiderPos = [
    [103, 242],
    [155, 260],
    [134, 292],
    [160, 311],
    [223, 290],
    [207, 299],
    [192, 304],
    [200, 328],
    [185, 322],
    [193, 362],
    [205, 347],
    [220, 374],
    [172, 377],
    [193, 405],
    [166, 399],
    [240, 422],
    [215, 428],
    [182, 430],
    [140, 410],
    [157, 339],
    [151, 362],
    [130, 315],
    [113, 347],
    [229, 413],
    [125, 377],
    [101, 389],
    [82, 356],
    [37, 397],
    [110, 429],
    [88, 440],
    [223, 459],
    [176, 468],
    [197, 488],
    [275, 450],
    [261, 436],
    [220, 476],
    [236, 518],
    [191, 536],
    [146, 546],
    [160, 518],
    [92, 480],
    [260, 543],
    [236, 582],
    [269, 284],
    [255, 289],
    [252, 313],
    [229, 314],
    [251, 334],
    [254, 378],
    [281, 384],
    [295, 271],
    [303, 286],
    [285, 300],
    [289, 331],
    [291, 352],
    [311, 338],
    [322, 318],
    [320, 292],
    [333, 340],
    [321, 380],
    [346, 361],
    [332, 403],
    [345, 429],
    [308, 428],
    [334, 449],
    [377, 415],
    [373, 391],
    [320, 492],
    [312, 476],
    [349, 484],
    [345, 502],
    [337, 548],
    [318, 529],
    [376, 510],
    [406, 375],
    [381, 352],
    [361, 301],
    [85, 539],
    [54, 575],
    [101, 610],
    [396, 301],
    [416, 317],
    [398, 338],
    [445, 325],
    [436, 352],
    [416, 397],
    [387, 448],
    [384, 481],
    [457, 437],
    [435, 484],
    [470, 352],
    [431, 555]
];

//sets normal game state with timer at 0
var gameState = "menu";
var timer = 0;

//preloads background image
function preload() {
    bg = loadImage("assets/spiderbg.png");
}

function setup() {
    createCanvas(500, 668);
    //sets random values for x position of portal
    ran1 = random(100, 400);
    //sets random values for y position of portal
    ran2 = random(550, 600);
    //creates sprite for the portal at random position 
    //and assigns animation
    portalSprite = createSprite(ran1, ran2);
    portalSprite.addAnimation("normal", "assets/portal0000.png", "assets/portal0002.png")
        //scales the portal to be smaller
    portalSprite.scale = .2;
    //slows down the frame rate of the animation
    portalSprite.animation.frameDelay = 20;

    //creates particle group for rain
    particles = new Group();
    //assign new sprites to groups
    for (var i = 0; i < 100; i++) {
        //puts all creation and initialization instructions in a 
        //premade function found at bottom of code
        createParticle();
    }

    //creates sprite group for spiders
    spiders = new Group();
    //for loop to create all spiders at positions in position array
    for (var i = 0; i < spiderPos.length; i++) {
        //creates spider sprites at specified positions
        var s = createSprite(spiderPos[i][0], spiderPos[i][1]);
        //animation for spiders in normal state
        s.addAnimation("playing", "assets/spider0000.png", "assets/spider0009.png");
        //plays the spider animation starting at different frames
        var f = floor(random(0, s.animation.getLastFrame()));
        s.animation.changeFrame(f);
        //animation for spiders when they're looking at you before game ends
        s.addAnimation("looking", "assets/spider0010.png", "assets/spider0012.png");
        //sets the circle around the spider which ends the game when touched
        s.setCollider("circle", 0, 0, 90);
        //increases the size of the spider as the y position increases
        //by indexing into the position array and multiplying by decimal
        var spiderSize = 0.04;
        s.scale = spiderSize * .005 * (spiderPos[i][1]);
        //trigger the looking function + looking animation when
        //mouse goes over the spider collider
        s.onMouseOver = function() {
                //changes animation to looking animation
                looking(spiders);
            }
        //add spider sprites
        spiders.add(s);
    }
}

//function for when you touch a spider and
//it looks at you and the game ends
function looking(g) {
    if (gameState == "game") {
        for (var i = 0; i < g.length; i++) {
            var sp = g[i];
            sp.changeAnimation("looking");
            //delays frame rate of animation
            sp.animation.frameDelay = 10;
        }
        gameState = "looking";
        //adds timer to countdown to game over state 
        //after the looking animation is triggered
        timer = 60;
    }
}

function draw() {
    background(255);
    //sets up the menu state with text and background
    if (gameState == "menu") {
        s = "OH NO! You have fallen down a sewer and have been plunged into a fantastical realm. Reach the portal swiftly to get back to the human realm without coming into contact with the spiders. Good luck! Click anywhere to begin."
        background(0)
        textSize(30);
        fill(156, 183, 226)
        text(s, 10, 10, 400, 400);
        s2 = "This fantasy realm, The Conjured Isles, is inhabited by hundred eyed spiders who are extremely wise. They usually pass their time playing in never ending rain. They live ontop of lillypads in the blood river. They are currently ruled by a mysterious creature that looms over the realm atop a black cloud, whom the people respect intensely."
        textSize(20);
        fill(156, 183, 226)
        text(s2, 10, 450, 400, 600);
        //on clicking on the screen the game starts + goes into "game" state
        if (mouseIsPressed) {
            gameState = "game";
        }
    }
    //draw sprites if the game state changes from menu
    if (gameState != "menu") {
        drawSprites();
        //counts down from timer once game state goes into "looking" and
        //at 0 the game state changes to "gameOver"
        if (gameState == "looking") {
            timer--;
            if (timer <= 0) {
                gameState = "gameOver";
            }
        }
        //sets up the game over state with text and background
        if (gameState == "gameOver") {
            background(0);
            s3 = "You were seen and banished by the spiders before you could reach the human realm. Better luck next time!"
            textSize(30);
            fill(156, 183, 226)
            text(s3, 10, 10, 400, 400);
            //if game state is not "gameOver" display normal background
        } else {
            image(bg);
            //if the mouse is within the bounds of the portal, 
            //change game state to won
            if (gameState == "game" & mouseX < ran1 + 25 && mouseX > ran1 - 25 &&
                mouseY < ran2 + 25 && mouseY > ran2 - 25) {
                gameState = "won";
            }
            //if the mouse gets too close to the left and right side
            //and the bottom side, (for cheaters), end game
            if (gameState == "game" & mouseX < 10 || mouseX > width - 10 || mouseY > height - 10) {
                gameState = "gameOver"
            }
            //sets up the won state with text and background
            //removes sprites
            if (gameState == "won") {
                background(0);
                s4 = "You reached successfully the portal and returned to the human realm! Congrats!"
                textSize(30);
                fill(156, 183, 226)
                text(s4, 10, 10, 400, 400);
                s.remove();
            }
            //code to draw the rain particles
            for (var i = 0; i < particles.length; i++) {
                //stores the particle in a temporary variable called p
                var p = particles[i];
                //scales it down
                p.scale = 0.15;
                //moves all the y positions of the particles down
                //for rain falling effect
                p.position.y += 10;
                //wraps particle to the top when it reaches the bottom
                if (p.position.y > height) {
                    p.position.y = -50;
                }
            }
            //draw all sprites
            drawSprites();
        }
    }
}
//function to create the rain particle
function createParticle() {
    //creates a sprite at a random position
    var newParticle = createSprite(random(0, width), random(0, height));
    //assigns an animation
    newParticle.addAnimation("falling", "assets/cloud.png");
    //adds it to the particle group
    particles.add(newParticle);
}

Here are screenshots of the game also:

^ the menu page

^the game in its normal state

^ the game when the player touches a spider

^ the game over state

^ the winning state

For this project I wanted to create a game based mostly on graphics, visuals, and backgrounds. I wanted to create a game where the player has to navigate through a tricky trap-like environment. The player has to avoid coming into contact with the inhabitants of an imaginary realm while hurrying to reach a portal to get back to the human realm. They have to navigate through a mob of spiders resting on top of lillypads without touching them and being seen. This project was really fun for me, despite having to code the positions of the spiders individually so that they would fit nicely on top of the lillypads that I chose. I really enjoyed making the background in particular, which I made for this project by painting first in watercolor, then scanning into photoshop and drawing ontop of it digitally. I also really enjoyed coming up with the narrative aspect of the project, and the world building.

rgroves – Final – Section B

sketch

//vertices and edge sets of the individual graphs
var V = [];
var E = [];

//total set of vertices
var vertices = [];
var spacing = 48;

//buttons for coloring vertices
var redbutton;
var bluebutton;
var greenbutton;
var pinkbutton;
var orangebutton
var buttons = [];

var levelnumber = 1;
var mousehasentbeenclicked;

function setup() {
    createCanvas(480, 400);
    background(255);
    resetLevel();
}

function resetLevel() {
	mousehasentbeenclicked = true;
	 background(255);
    //create buttons
    redbutton = makeButton(width/6, color(209, 90, 90));
	bluebutton = makeButton(2 * width/6, color(93, 137, 196));
	greenbutton = makeButton(3 * width/6, color(199, 197, 71));
	pinkbutton = makeButton(4 * width/6, 'lightpink');
	orangebutton = makeButton(5 * width/6, 'orange');
	buttons = [redbutton, bluebutton, greenbutton, pinkbutton, orangebutton];
	for (i = 0; i < buttons.length; i++) {
		buttons[i].isoutlined = false;
		buttons[i].draw();
	}

	//draw grid of small vertices and label them from 0 to 53 in an array
    for (i = 0; i < width/spacing - 1; i++) {
    	for (j = 0; j < 300/spacing - 1; j++) {
	   		vertices[i + ((width/spacing - 1) * j)] = 
	   		makeVertex(spacing + i * spacing, spacing + j * spacing);
    	}
    }
}

//OBJECTS: VERTICES, EDGES, BUTTONS////////////////////////////////////////////

//vertices
function vertexboldDraw() {
	noStroke();
	if (this.isred == true) {
		fill(209, 90, 90);
		ellipse(this.x, this.y, 16, 16);	
	} else if (this.isblue == true) {
		fill(93, 137, 196);
		ellipse(this.x, this.y, 16, 16);	
	} else if (this.isgreen == true) {
		fill(199, 197, 71);
		ellipse(this.x, this.y, 16, 16);	
	} else if (this.ispink == true) {
		fill('lightpink');
		ellipse(this.x, this.y, 16, 16);
	} else if (this.isorange == true) {
		fill('orange');
		ellipse(this.x, this.y, 16, 16);
	} else {
		stroke(150);
		strokeWeight(1);
		fill(255);	
		ellipse(this.x, this.y, 15, 15);	
	}
}

function vertexDraw() {
	noStroke();
	fill(180);
	ellipse(this.x, this.y, 1.5, 1.5);
}

function makeVertex(px, py) {
	v = {x: px, y: py, draw: vertexDraw, bolddraw: vertexboldDraw,
		isred: false, isgreen: false, isblue: false, ispink: false,
		isorange: false};
	return v;
}

//edges
function edgeDraw(m, n) {
	if (this.iscolored == true & this.iscorrect == true) {
		strokeWeight(3);
		stroke('limegreen');
	} else if (this.iscolored == true & this.iscorrect == false) {
		strokeWeight(3);
		stroke('tomato');
	} else if (this.iscolored == false) {
		strokeWeight(.5);
		stroke(200);
	}
    line(vertices[this.m].x, vertices[this.m].y,
    vertices[this.n].x, vertices[this.n].y);
}

function makeEdge(pm, pn) {
	e = {m: pm, n: pn, iscolored: false, iscorrect: true, draw: edgeDraw};
	return e
}

//buttons
function buttonDraw() {
	rectMode(CENTER);
	if (this.isoutlined == true) {
		strokeWeight(3);
		stroke(255);
		fill(this.buttoncolor);
		rect(this.x, height - 50, 60, 20);
	} else {
		noStroke();
		fill(this.buttoncolor);
		rect(this.x, height - 50, 61.5, 21.5);
	}	
	
}

function makeButton(px, color) {
	b = {x: px, buttoncolor: color, isoutlined: false, draw: buttonDraw};
	return b;
}

//FUNCTIONS TO BE CALLED IN MOUSEPRESSED///////////////////////////////////////
function testEdge() {
	//edges are green if the vertices are different color and red if they are 
	//the same colors
	for (i = 0; i < E.length; i++) {
		if (vertices[E[i].m].isred == true & vertices[E[i].n].isred == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].isblue == true & vertices[E[i].n].isblue == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].isgreen == true & vertices[E[i].n].isgreen == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].ispink == true & vertices[E[i].n].ispink == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].isorange == true & vertices[E[i].n].isorange == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if ((vertices[E[i].m].isred == true || vertices[E[i].m].isblue == true ||
			vertices[E[i].m].isgreen == true || vertices[E[i].m].ispink == true
			|| vertices[E[i].m].isorange == true) & (vertices[E[i].n].isred == true 
			|| vertices[E[i].n].isblue == true || vertices[E[i].n].isgreen == true
			|| vertices[E[i].n].ispink == true || vertices[E[i].n].isorange == true)) {
			E[i].iscolored = true;
		}
		if (E[i].iscolored == true & (vertices[E[i].m].isred !== vertices[E[i].n].isred
			|| vertices[E[i].m].isblue !== vertices[E[i].n].isblue
		    || vertices[E[i].m].isgreen !== vertices[E[i].n].isgreen 
		    || vertices[E[i].m].ispink !== vertices[E[i].n].ispink
		    || vertices[E[i].m].isorange !== vertices[E[i].n].isorange)) {
			E[i].iscolored = true;
			E[i].iscorrect = true;
		}
		E[i].draw();
	}
}

function colorVertices() {
	//change colors of vertices when clicked, depending on which button has 
	//most recently been clicked
	for (i = 0; i < V.length; i++) {
		if (dist(mouseX, mouseY, vertices[V[i]].x, vertices[V[i]].y) < 10) {
			if (buttons[0].isoutlined == true & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = true;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == true &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = true;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == true && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = true;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == true &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = true;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == true) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = true;
			}
		}
	}
}

function pressButton() {
	//select color for vertex coloring
	if (mouseX >= buttons[0].x - 30 & mouseX <= buttons[0].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = true;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[1].x - 30 & mouseX <= buttons[1].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = true;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[2].x - 30 & mouseX <= buttons[2].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = true;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[3].x - 30 & mouseX <= buttons[3].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = true;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[4].x - 30 & mouseX <= buttons[4].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = true;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
}

//DESIGN LEVELS AND CALL THEM IN DRAW//////////////////////////////////////////
function levelOne() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level One: Practice', 30, 10);
	E = [[25, 4], [19, 4], [25, 51], [51, 47], [47, 19], [4, 13], [25, 24], 
	[51, 41], [47, 39], [19, 20], [13, 41], [41, 20], [20, 24], [24, 39], 
	[39, 13]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 13, 19, 20, 24, 25, 39, 41, 47, 51];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 	
}

function levelTwo() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Two', 30, 10);
	E = [[25, 4], [19, 4], [25, 51], [51, 47], [47, 19], [38, 47], [47, 51], 
	[51, 42], [42, 38], [38, 51], [42, 47], [42, 19], [25, 38], [4, 38], 
	[4, 42], [19, 38], [25, 42]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 19, 25, 38, 42, 47, 51];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 	
}

function levelThree() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Three', 30, 10);
	E = [[4, 31], [31, 17], [31, 53], [31, 45], [31, 9], [12, 14], [14, 33], 
	[33, 40], [40, 29], [29, 12], [4, 29], [4, 14], [17, 12], [17, 33], [53, 14], 
	[53, 40], [45, 33], [45, 29], [9, 40], [9, 12]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 9, 12, 14, 17, 29, 33, 40, 45, 53, 31];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 
		
}

function levelFour() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Four', 30, 10);
	E = [[4, 18], [18, 45], [45, 21], [21, 4], [4, 23], [23, 53], [53, 26], 
	[26, 4], [4, 28], [4, 34], [28, 34], [18, 28], [26, 34], [18, 21], 
	[23, 26], [28, 21], [34, 23], [21, 23], [28, 34], [23, 45], [21, 53]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 18, 21, 23, 26, 28, 34, 45, 53];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 
}

function levelFive() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Five', 30, 10);
	E = [[25, 4], [19, 4], [25, 51], [51, 47], [47, 19], [4, 13], [19, 13], 
	[25, 13], [29, 13], [33, 13], [47, 13], [51, 13], [4, 29], [4, 33], 
	[19, 29], [25, 33], [29, 51], [33, 47], [29, 47], [33, 51], [25, 29], [19, 33]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 19, 25, 47, 51, 13, 33, 29];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 
}



function draw() {
	for (k = 0; k < vertices.length; k++) {
    	vertices[k].draw();
    }
    if (levelnumber == 1) {
    	levelOne();
    } else if (levelnumber == 2) {
    	levelTwo();
    } else if (levelnumber == 3) {
    	levelThree();
    } else if (levelnumber == 4) {
    	levelFour();
    } else if (levelnumber == 5) {
    	levelFive();
    }
}


function mousePressed() { 
	mousehasentbeenclicked = false;
	pressButton();
	colorVertices();
	testEdge();	

	var is5colored = true;
	for (i = 0; i < E.length; i ++) {
		if (E[i].iscolored == false || E[i].iscorrect == false) {
			is5colored = false;
		}
	}
	if (is5colored == true) {
		resetLevel();
		levelnumber++;
	}
	if (levelnumber == 6) {
		textSize(90);
		fill('lightpink');
		noStroke();
		text('YOU WIN', 40, height/2);
	}			
}

My final project is a simple game based on graph coloring. Click on any of the colored boxes to select a color and then click in the vertices to color them with that color. The goal is to color in the graph so that there is no edge between vertices of the same color. When you succeed it will automatically move on to the next level. There are a total of 5 levels and when you complete them all you win!

ghou-Final-Project

I wanted to create an interactive and hopefully addicting mini-game. This project is inspired by the old arcade games I used to spend all my allowance on to win the big prize at the top! Also the final stacked blocks of my project looks similar to a modern skyscraper building in the grey skylines.

sketch

//Grace Wanying Hou
//15-104 Section D
//ghou@andrew.cmu.edu
//Final Project

//blocks dimensions setup
var h = 20;
var w = 100;
var x = 0;
var y = 20;
var speed = 1;
var fall = 5;
var dropping = false;
var taps = 0;

//arrays
var blocks = [];
var land = [75];

//gameplay
var play = false;
var gameOver = false;
var win = false;


function setup() {
    createCanvas(250, 400);
    frameRate(50);
    
}
 
function draw(){
    noStroke();
    if (gameOver == true){
        if (play == true){//game screen once "gameover"
            makeBackground();
            text("YOUR SCORE WAS " + taps, 60, height - h*taps - 2 * h);
            text("PRESS ANY KEY TO PLAY AGAIN", 28, height - h * taps - h);
            push();
            textSize(10);
            text("screenshot and share your architecture masterpiece :)", 5, 30)//hehe i like architecture
            pop();
            updateDisplay();
        }

        if (win == true){//game screen once player wins
            makeBackground();
            text("YOU WIN",100,40);
            text("PRESS ANY KEY TO PLAY AGAIN", 28, height/2);
            push();
            textSize(10);
            text("screenshot and share your architecture masterpiece :)", 5, 30)
            pop();
            updateDisplay();
        }
        //resetting the variables when restarting game
        if (keyIsPressed){
            gameOver = false;
            play = false;
            win = false;
            blocks = [];
            land = [75];
            dropping = false;
            w = 100;
            x = 0;
            y = 20;
            speed = 1;
            fall = 5;
            taps = 0;
        }
    }
    
    else if (play == true){//screen once game starts
            makeBackground();
            text("PRESS SPACE TO STACK BLOCKS", 30, height/2);
            for (var i = 0; i < 3; i++){
                var xstart = width / 2 - 50;
                var ystart = height - 20;
                blocks[i] = makeBlock(xstart, ystart, 100);
            }//gameplay functions
            blockDrop();
            drawBlock();
            blockMove();
            addBase();
            updateDisplay();
            scoreDisplay();
    }
    
    else {
        if (play == false){//starting screen
            makeBackground();
            text("PRESS ANY KEY TO BEGIN GAME", 28, height/2);
            if (keyIsPressed == true){
                play = true;
            }
        }
    }
    
    if (w <= 0){
        gameOver = true;
        play = true;
    }
    
    else if (taps >= 16 & y >= 50){
        gameOver = true;
        win = true;   
    }
}

function makeBackground(){//making a gradient for the background
    strokeWeight(1);
    for (var i = 0; i < height; i++){
        stroke(255 - i / 8);
        line(0, i, width, i);
    }
}

function blockMove(){//hovering blocks moving side to side
    if (x >= width - w){
        speed = -1 - (taps * 0.2);
    }
    else if(x <= 0){
        speed = 1+(taps * 0.2);
    }
    x = x + speed;
}

function blockDrop(){//dropping blocks
    if (dropping == true){
        y = y + fall;
        speed = 0;
        while (y > height - h * taps){
            dropping = false;
            y = 20;
            speed = 1 + (taps * 0.2);
            fall = 5;
        }
    }
}

function keyTyped(){//setting the blocks to drop once space is pressed
    if (keyCode == 32 & dropping == false && play == true){
        taps = taps + 1;
        append(land, x);
        dropping = true;
    }
}

function drawBlock(){//drawing hovering block
    noStroke();
    fill(0);
    rect(x,y,w,h);
}


function scoreDisplay(){//displaying score (numbers of blocks fallen)
    push();
    fill(255);
    textSize(15);
    text(taps,120,height-5);
    pop();

}
    
function addBase(){//knida confusing measurements of blocks collected in the tower
    var currenth = height - taps * h - h;//current height of tower
    if (y == height - h * taps){//if falling blocks are on the LEFT side of the tower
        if (land[taps] <= land[taps - 1]){
            blocks.push(makeBlock(land[taps - 1], currenth ,w - (land[taps - 1] - land[taps])));
            w = w - (land[taps - 1] - land[taps]);
            shorten(land);
            append(land, land[taps-1]);
        }
        else if (land[taps] > land[taps - 1]){//if falling blocks are on the RIGHT side of the tower
             blocks.push(makeBlock(land[taps], currenth, w - (land[taps] - land[taps - 1])));
             w = w - (land[taps] - land[taps - 1]);
        }
    }
}

function updateDisplay(){//drawing and updating the display of the stacked blocks
    for (var i = 0; i < blocks.length; i++){
        blocks[i].add();
    }
}

function towerBlocks(){//drawing the blocks in the tower
    noStroke();
    fill(0);
    rect(this.x, this.y, this.bw, this.bh);
}

//objects created for each block in the tower
function makeBlock(xlocation, ylocation, currentwidth){
    var block = {x:xlocation,
                 y:ylocation,
                 bh:20,
                 bw:currentwidth,
                 add:towerBlocks,
                 }
    return block;
}

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