hschung-Final-Project

sketch

//Heidi Chung
//hschung
//Section A
//Final-Project

var clouds = [];
var bobaY = 0; // height of boba
var bobaDy = 0; // the vertical velocity of boba
var offset = 0;
var themeSong; //variable for song to be played
var blush = 200; //variable to make boba change color and "blush"

function preload() {
  themeSong = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/bobasong.mp3");
  //preloading the song Boba Beach by Grynperet
}

function newcloud(px, py, pw) { //object for clouds
    return {x: px, y: py, w: pw};
}

function setup() {
    createCanvas(450, 400);
    clouds.push(newcloud(600, 200, 200));//adding a new cloud
    themeSong.play(); //play the song
    amplitude = new p5.Amplitude(); //capturing the volume of the song
}

// compute the location of the right end of a cloud
function cloudRight(p) {
    return p.x + p.w;
}

// return the last cloud object
function cloudLast() {
    return clouds[clouds.length - 1];
}

function draw() {
    background(253, 225, 200);
    var bobaX = width / 2;
    drawGreeting(); //calling the greeting and its "shadow" to be drawn
    drawBoba(); //calling the boba to be drawn
      push();
      noStroke(); //multiple layers to achieve pleasant transparency
      fill(255, 99);//white sea foam
      rect(0, height - 70, width, 70);
      fill(177, 156, 217, 90);//lilac sea foam 2
      rect(0, height - 80, width, 80);
      fill(220, 200, 200, 90);//sea foam 3
      rect(0, height - 90, width, 90);
      fill(220, 200, 200);//solid background of sea
      rect(0, height - 60, width, 60);
      fill(177, 156, 217, 90);//the taro sea
      rect(0, height - 60, width, 60);
      pop();
    stroke(255);
    strokeWeight(3);
    var level = amplitude.getLevel();
    var cloudSize = map(level, 0, 1, 30, 50);
    //clouds' height wiggles in response to song volume
    for (var i = 0; i < clouds.length; i++) {
        var p = clouds[i];
        noStroke();
        fill(255); //white clouds
        ellipse(p.x - offset, p.y, p.w, cloudSize);
    }

    // if first cloud is offscreen to left, remove it
    if (clouds.length > 0 & cloudRight(clouds[0]) < offset) {
        clouds.shift();
    }
    // if last cloud is totally within canvas, make a new one
    if (cloudRight(cloudLast()) - offset < width) {
        var p = newcloud(cloudRight(cloudLast()), // start location
                            random(50, 320), // height of new cloud
                            140); // all clouds have width 140 for now
        clouds.push(p); //add to array of clouds
    }
    noStroke();
    // move the "landscape"
    // move and draw the "boba"
    //which cloud is current? linear search (!) through clouds
    var pindex = 0;
    while (cloudRight(clouds[pindex]) - offset + 20 < bobaX) {
        pindex += 1;
    }
    //now pindex is index of the cloud in the middle of canvas
    //find the cloud height
    var py = clouds[pindex].y;
    //if boba is above a cloud, fall toward it, but don't go past it
    if (bobaY <= py) {
        bobaY = min(py, bobaY + bobaDy); // change Y by Dy
    } else { // if we are below the cloud, fall to ground
      //to avoid this, once we are below a cloud, force Dy non-negative
      if (bobaDy < 0) {
          bobaDy = 0;
      }
      bobaY = min(height, bobaY + bobaDy);
    }
    //if the boba falls from a cloud, it will "jump" to the next cloud
    if (bobaY >= height) {
        bobaY = 0;
    }
    //move the "landscape"
    offset += 3;
    //accelerate boba with gravity
    bobaDy = bobaDy + 1;
}

function drawGreeting() {
  var level = amplitude.getLevel();
  var greetingSize = map(level, 0, 1, 25, 30); //control limits of greeting size
  for (i = 0; i < width; i++) {
    fill(210, 120, 120);
    textSize(greetingSize);
    text("welcome  to  boba  beach", width/5 + i, height/4 + i); //streaked greetings
  }
  fill(255, 196, 197); //light pink greeting
  strokeWeight(3);
  textSize(greetingSize);
  text("welcome  to  boba  beach", width/5, height/4);
}

function drawBoba() {
  var bobaX = width / 2;
  var level = amplitude.getLevel();
  var bobaSize = map(level, 0, 1, 35, 85); //control limits of boba size
  var eyeSize = map(level, 0, 1, 5, 10); //control limits of eye size
  //traits fluctuate in size depending on the song's volume.
  var mouthSize = map(level, 0, 1, 7, 15); //control limits of mouth size

  fill(blush - 100, 120, 120); //boba "blushes" when you make it jump by pressing any key
  noStroke();
  fill(230, 130, 140);
  ellipse(bobaX, bobaY - 20, bobaSize, bobaSize); //jumping boba
  fill(0);
  ellipse(bobaX - 7, bobaY - 20, eyeSize, eyeSize); //left eye
  ellipse(bobaX + 11, bobaY - 25, eyeSize, eyeSize); //right eye
  fill(120, 0, 32); //happy mouth
  arc(bobaX + 4, bobaY - 20, mouthSize + 3, mouthSize + 3, 0, PI + 50, CHORD);
}

function keyPressed() {
  bobaDy = -15; //velocity set to up when key is pressed
    if (blush === 200) { //changing the color of the boba
      blush = 255; //if the boba's R value is 200, and a key is pressed,
    } else {       //change the R value to 255, and vice-versa.
      blush = 200;
    }
}

For my final project, wanted to create a cute, simple, and clean animation with an interactive touchpoint- perhaps by pressing keys or clicking the mouse. My inspiration was to create something that brings the user a sense of delight. I wanted to animate with AfterEffects using the soundtrack “Boba Beach” and I attempted to over the summer, but didn’t finish, and that led me to want to create a cute thing for the final project. I was inspired by the delight and familiarity of platform games, and thought it would mesh well with my idea of having cute visuals that you can interact with if you so choose. I chose not to make the boba “die” when it falls off the clouds, like a classic platform game.

The jumping boba wiggles in size depending on the volume of the song, as do its eyes and mouth. The clouds passing by also wiggle. When you press any key, the boba will change color slightly and “blush” and it jumps as well. The greeting in the background also wiggles with the volume. I am pleased with the cute aesthetics and interaction I was able to make.

doodlings for composition ideating
I made these assets in Illustrator and had tried animating them with AfterEffects. This also served as color scheme inspiration.
screenshot: a little boba floating on a cloud above a sea of taro tea

katieche – final project

final project

// BORROWED FROM IRA GREENBERG
var radius = 45, rotAngle = -90;
var accelX = 0.0, accelY = 0.0;
var deltaX = 0.0, deltaY = 0.0;
var springing = 0.0009, damping = 0.98;

//corner nodes
var nodes = 5;

//zero fill arrays
var nodeStartX = [];
var nodeStartY = [];
var nodeX = [];
var nodeY = [];
var angle = [];
var frequency = []; // END OF BORROWED CODE

// array for the rings and boxes
var rings = [];
var boxes = [];

// initializing colors for keypressed changes
var r = 250;
var g = 250;
var b = 250;

var frames = [];

//var score = 0;

function preload() { // loading ring popping animation frames
	var f = [];
		f[0] = "https://i.imgur.com/AZJNy6P.png";
		f[1] = "https://i.imgur.com/coAJvFm.png";
		f[2] = "https://i.imgur.com/Y3RE12y.png";
		f[3] = "https://i.imgur.com/9sTJNBz.png";


		for(var i =0; i < 4; i++){
			frames[i] = loadImage(f[i]);
		}
}


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


  // BORROWED FROM IRA GREENBERG: initialize arrays to 0
  for (var i=0; i<nodes; i++){
    nodeStartX[i] = 0;
    nodeStartY[i] = 0;
    nodeY[i] = 0;
    nodeY[i] = 0;
    angle[i] = 0;
  } // END OF BORROWED CODE

  // initializes collection of rings 
  for (var i = 0; i < 3; i++){
    	var ry = random(-300, 0); //rings are falling from above the canvas at random
        rings[i] = makeRing(ry);
        boxes[i] = makeBox(ry);
        }

  // BORROWED FROM IRA GREENBERG: iniitalize frequencies for corner nodes
  for (var i = 0; i < nodes; i++){
    frequency[i] = random(4, 5);
  } // END OF BORROWED CODE

  noStroke();
  frameRate(30);
}

function draw() {
	fill(50);
	rect(0,0,width, height);

	// display rings + boxes
	updateAndDisplayRings();
	ringAdd();

	updateAndDisplayBox();
	boxAdd();

	// for the character
  	drawShape();
  	moveShape();

  	// instructional text
  	text("press 'Q' to eat blue, 'W' to eat pink, 'E' to eat yellow", 180, 450);


}
// CHARACTER
// CODE IS BASED ON IRA GREENBERG'S SOFT BODY EXAMPLE:
// https://p5js.org/examples/simulate-soft-body.html
// HAS BEEN HEAVILY EDITED BY ME
function drawShape() {
  //  calculate node  starting locations
  for (var i=0; i<nodes; i++){
    nodeStartX[i] = mouseX+cos(radians(rotAngle))*radius;
    nodeStartY[i] = mouseY+sin(radians(rotAngle))*radius;
    rotAngle += 360.0/nodes;
  }

  // draw polygon
  curveTightness(0.5); // to create soft body like organic shape
  noStroke();
  fill(r,g,b);
  beginShape();
  // creates a point at each (nodeX, nodeY) for the 5 corners in the array
  for (var i=0; i<nodes; i++){
    curveVertex(nodeX[i], nodeY[i]);
  }
  // to make shape connect all the way around
  for (var i=0; i<nodes-1; i++){
    curveVertex(nodeX[i], nodeY[i]);
  }
  endShape(CLOSE); // END OF BORROWED CODE

  // eyes
  fill(149, 166, 193);
  ellipse(mouseX+30, mouseY, 10, 10);
  ellipse(mouseX-30, mouseY, 10, 10);

  push();
  noFill();
  stroke(149, 166, 193);
  strokeWeight(3);
  ellipse(mouseX+30, mouseY, 15, 15);
  ellipse(mouseX-30, mouseY, 15, 15);
  pop();
}


function moveShape() { // BORROWED FROM IRA GREENBERG
  //move center point
  deltaX = mouseX;
  deltaY = mouseY;

   //create springing effect
  deltaX *= springing;
  deltaY *= springing;
  accelX += deltaX*0.8;
  accelY += deltaY*0.8;

  // slow down springing
  accelX *= damping;
  accelY *= damping;

  //move nodes
  for (var i=0; i<nodes; i++){
    nodeX[i] = nodeStartX[i]+sin(radians(angle[i]))*(accelX);
    nodeY[i] = nodeStartY[i]+sin(radians(angle[i]))*(accelY);
    angle[i] += frequency[i];
  }
} // END OF BORROWED CODE

function keyPressed() { // changes blob's color

    if(keyCode == 81) { // "Q" blue
        r = 202;
        g = 220;
        b = 247;
    }
    if(keyCode == 87) { // "W" pink
        r = 247;
        g = 207;
        b = 207;
    }
    if(keyCode == 69) { // "E" yellow
        r = 255;
        g = 241;
        b = 193;
    }
}

// RINGS
function updateAndDisplayRings(){
    // Update the rings positions, and display them.
    for (var i = 0; i < rings.length; i++){
        rings[i].move();
        rings[i].display();
    }
}


function ringAdd() {
    // With a very tiny probability, add a new ring to the end.
    var newringLikelihood = 0.02; 
    if (random(0,1) < newringLikelihood) {
        rings.push(makeRing(0));
        rings.push(makeRing(0));

    }
}

// moving the rings
function ringMove() {
    this.y += this.speed;

}
    
// drawing the rings
function ringDisplay() {
	noFill();
	stroke(210);
	strokeWeight(2);

	if (dist(mouseX, mouseY, this.x, this.y) <= 50) { // if the mouse is 50 points close to the ring, it pops
		this.isPopped = true;
		this.timePopped = frameCount; // record the framecount at which it pops
	}


	if (this.isPopped == false) { // if the state of the ring is not popped
		ellipse(this.x, this.y, this.diam, this.diam);
	}

	else {
		this.popped(); // if this.isPopped == true, then calls ringPop which displays pop animation

	}


}

function ringPop() { // animating rings popping
	var num = frameCount-this.timePopped;
	if (num >= frames.length) {
		// if num goes past the number of animation frames, the pop dissapears
	}
	
	else {
    image(frames[num], this.x, this.y, 50, 50);
	}
}


// making the rings
function makeRing(cy) {
    var ring = {y: cy,
    			x: random(0,600),
    			diam: random(15,25),
 				speed: random(2.0, 3.0),
                move: ringMove,
                display: ringDisplay,
                isPopped: false,
                popped: ringPop,
                timePopped: -10
            }
    return ring;
}

// SQUARES
function updateAndDisplayBox(){
    // Update the clouds' positions, and display them.
    for (var i = 0; i < boxes.length; i++){
        boxes[i].bmove();
        boxes[i].bdisplay();
    }
}


function boxAdd() {
    // With a very tiny probability, add a new ring to the end.
    var newboxLikelihood = 0.02; 
    if (random(0,1) < newboxLikelihood) {
        boxes.push(makeBox(0));
    }
}

// moving the rings
function boxMove() {
    this.by += this.bspeed;
    this.py += this.pspeed;
    this.yy += this.yspeed;

}
    
// drawing the rings
function boxDisplay() {

	// blue box
	if (dist(mouseX, mouseY, this.bx, this.by) <= 50 & r == 202 && g == 220 && b == 247) { 
	// if the mouse is 50 points close to the box and the blob is blue
		this.bisEaten= true;
	}


	if (this.bisEaten == false) { // if the state of the box is not eaten
		noStroke();
		fill(202, 220, 247);
		rect(this.bx, this.by, this.bs, this.bs, 5);
	}

	else {
	}

	// pink box
	if (dist(mouseX, mouseY, this.px, this.py) <= 50 & r == 247 && g == 207 && b == 207) { 
	// if the mouse is 50 points close to the box and the blob is pink
		this.pisEaten = true;
	}


	if (this.pisEaten == false) { // if the state of the box is not eaten
		noStroke();
		fill(247, 205, 202);
		rect(this.px, this.py, this.bs, this.bs, 5);
	}

	else {
		// box disapears when state is true
	}

	// yellow box
	if (dist(mouseX, mouseY, this.yx, this.yy) <= 50 & r == 255 && g == 241 && b == 193) { 
	// if the mouse is 50 points close to the box and the blob is pink
		this.yisEaten = true;
	}

	if (this.yisEaten == false) { // if the state of the box is not eaten
		noStroke();
		fill(255, 241, 193);
		rect(this.yx, this.yy, this.bs, this.bs, 5);
	}

	else {
		// box disapears when state is true
	}

}

// making the rings
function makeBox(ty) {
    var box = {	// blue box coord
    			by: ty,
    			bx: random(0,600),
    			// pink box coord
    			py: random(0,200),
    			px: random(0,600),
    			// yellow box coord
    			yy: random(0,200),
    			yx: random(0,600),

    			bs: random(20,25),
 				bspeed: random(1.0, 2.0),
 				pspeed: random(1.0, 2.0),
 				yspeed: random(1.0, 2.0),
                bmove: boxMove,
                bdisplay: boxDisplay,

                bisEaten: false, // blue false
                pisEaten: false, // pink false
                yisEaten: false, // yellow false
            }
    return box;
}

For my final project, I wanted to create a game with a fun ambiguous character. In a way, the game is like a fight between an organic shape and geometric shapes. It’s slightly different from my proposal but I like the way it turned out. It uses a modified version of the generative landscape functions, making the terrain (falling objects) fall downwards instead of sideways. It was difficult to modify the code so that the shapes would fall in a way that was relatively even, and not in lines or waves. The character is done using a heavily modified version of the soft body code found on the p5.js examples.

The objective of the game is to clear the screen! The rings pop whenever the character touches them, but the character’s own color must match up with the color of the squares to eat them. To change the character’s color, the player must select Q, W or E on their keyboard.

dnam final project

Title Page to the Game

Game Download

sketch

var terrainSpeed = 0.0005; //set up terrain details for the water effects
var terrainDetail = 0.005;
var smallFishs; //group for food
var fish; //main character
var sharks; 
var horses;
var smallRock;
var bigRock;
var deadImg;
var plant;
var img;
var fishImage; //set up for loading image
var sound;
var nE = 0; //number of fish eaten
var play = false;
var dead = false;
//set up coordinates for certain aspects in order to change them throughout code
var imgX = 0; 
var imgY = 0;
var textX = 450;

function preload() {

//load up the images from assets
fishImage = loadImage("assets/fish.png");
img = loadImage("assets/titl.png");
deadImg = loadImage("assets/ded.png");
bigRock = loadImage("assets/bigrock.png");
smallRock = loadImage("assets/smallrock.png");
plant = loadImage("assets/plant.png");
sound = loadSound('assets/boop.wav');
}

function setup() {
createCanvas(1000 , 600);

fish = createSprite(width/2, height/2); //spawn goldfish in the middle
//set movement limits to goldfish
fish.maxSpeed = 6; 
fish.friction = .9;
fish.setCollider();
//add the actual image into sprite variable
fish.addImage("normal", fishImage);

//set up groups 
smallFishs = new Group();
sharks = new Group();
horses = new Group();
}

function draw() {
//set up background of the game
  background(80, 80, 220);
  fill(150, 150, 0);
  noStroke();
  rect(0, 570, 1000, 100);
  image(smallRock, 1000, 490)
  push();
  scale(2);
  image(plant, 90, 255);
  pop();
  image(bigRock, 600, 480);
  image(smallRock, -250, 450);
  
//set up conditions for starting screen
if (play == false){
  image(img, imgX, imgY);
  
} else {
  drawWaves();

  fish.overlap(smallFishs, eatFish); //set up overlap for goldfish and food fish
  sharks.overlap(fish, sharkEat);
  
  //set up rotation speed / movement speed for gold fish
  if(keyDown(LEFT_ARROW)) {
    fish.rotation -= 2;
  }
  if(keyDown(RIGHT_ARROW)) {
    fish.rotation += 2;
  }
  if(keyDown(UP_ARROW)) {
    fish.addSpeed(.45, fish.rotation);
  }
  
  //come over on the other side if fish goes too far left/right
  if (fish.position.x > 1000) {
    fish.position.x = 0;
  } else if (fish.position.x < 0) {
    fish.position.x = 1000;
  }
  
  //come over on the other side if fish goes too far top/bottom
  if (fish.position.y > 600) {
    fish.position.y = 0;
  } else if(fish.position.y < 0){
    fish.position.y = 600;
  }
  
  //constantly create small fish randomly around the canvas
  if(random(0, 100) < 10) {
  var pn = random(360);
  var px = (width/2 + 1000) * cos(radians(pn));
  var py = (height/2 + 1000) * sin(radians(pn));
  createSmallFish(3, px, py);
  }
  
  //create sharks randomly but rarely
  if(random(0, 100) < 1) {
  var bn = random(300);
  var bx = (width/2 + 1000) * cos(radians(bn));
  var by = (height/2 + 1000) * sin(radians(bn));
  createShark(3, bx, by);
  }

  //constantly spawn seahorses, but rarely
  if(frameCount%70==0 & horses.length < 20) {
    createHorses(random(0,width), random(0,height));
  }
  for(var i = 0; i < horses.length; i++) {
      var sea = horses[i]; //create variable for seahorses
      sea.scale = map(sea.life, 220, 0, 1, 0); //lives for limited frames, changes sizes according to time
      sea.displace(fish); //push away and block goldfish's path
}
  drawSprites();
  text("Fishy Points: " + nE, textX, 50); //text showing current game points 
  }
}

function createSmallFish(x, y) { //function that builds small fish
  var smol = createSprite(x, y);
  var smolfish  = loadImage("assets/smallfish.png");
  smol.addImage(smolfish);
  smol.setSpeed(1, random(360));
  smol.rotationSpeed = .1;
  smol.setCollider("rectangle", 0, 0, 0, 0);
  smallFishs.add(smol);
  return smol;
}

function createShark(x, y) { //function that builds sharks
  var big = createSprite(-x, y);
  var bigShark = loadImage("assets/shark.png");
  big.addImage(bigShark);
  big.setSpeed(.5, random(360));
  big.rotationSpeed = .05
  big.setCollider("rectangle", 0, 0, 100, 10);
  sharks.add(big);
  return big;
}

function createHorses(x, y) { //function that builds seahorses with an animation that shrinks size
  var sea = createSprite(x, y);
  sea.addAnimation("horses", "assets/seahor.png");
  sea.life = 220;
  sea.rotationSpeed = .08
  sea.setCollider("rectangle", 0, 0, 0, 0);
  horses.add(sea);
}

function eatFish(fish, smallFishs) { //function to remove the small fish when overlapping as well as
  //adding on to fish eaten counter
  sound.play();
  nE += 1;
  smallFishs.remove();
}

function sharkEat(sharks, fish) {
  dead = true;
  play = false;

  if (dead == true) {
    imgX += 1000;
    imgY += 1000;
    textX += 1000;
    image(deadImg, 0, 0);
    fill(186, 217, 180);
    textSize(52.72);
    text("" + nE, 550, 321);
    noLoop();
  }
}

function keyPressed(){
  if (keyCode === 88){
    play = true;
  }
}

function drawWaves(){
  
  //wave 1
  fill(144,175,197, 60);
  beginShape();
  for (var x = 0; x < width; x++) {
      var t = (x * 0.003) + (millis() * terrainSpeed * 2);
      var y = map(noise(t), 0,1, 0, height * 0.1);
      vertex(x, y+ 1);
  }
  vertex(width,height);
  vertex(0,height);
  endShape();

  //wave 2
  fill(51,107,135, 60);
  beginShape();
  for (var x = 0; x < width; x++) {
      var t = (x * 0.003) + (millis() * terrainSpeed * 2);
      var y = map(noise(t), 0,1, 0, height * 0.1);
      vertex(x, y+50);
  }
  vertex(width,height);
  vertex(0,height);
  endShape();

  //wave 3
  fill(144,175,197, 60);
  beginShape();
  for (var x = 0; x < width; x++) {
      var t = (x * 0.003) + (millis() * terrainSpeed * 2);
      var y = map(noise(t), 0,1, 0, height * 0.1);
      vertex(x, y+65);
      if(noise(t) > 0.2){
        fill(144, 175, 197, 80);
      }
      else {
        fill(144,175,197,120);
      }
  }
  vertex(width,height);
  vertex(0,height);
  endShape();

  //wave 4
  fill(51,107,135, 60);
  beginShape();
  for (var x = 0; x < width; x++) {
      var t = (x * 0.003) + (millis() * terrainSpeed * 2);
      var y = map(noise(t), 0,1, 0, height * 0.1);
      vertex(x, y+100);
  }
  vertex(width,height);
  vertex(0,height);
  endShape();
}

The game is played by using the left / right arrow keys to change the rotation of the fish, and using the up arrow to move forward. Try to get as many points as possible by eating the smaller fish, while avoiding the angry sharks that will end the game if they touch you. The searhorses will stop your movement, so try to move around them.

Basing off how old styled games were formed, I wanted to make a game that has an unlimited ‘reward’ while having a losing condition. Using knowledge earned from the class, I was able to display and create the game I wanted to.

jwchou-final project-E

For my project, I decided to stay with the theme I had developed throughout the semester with plane-based projects.

The objective of the game is to fly the plane onto the runway while avoiding mountains and lightning. Instructions for running the game are included.

I had a really hard time with this project. My original concept was perhaps more interesting but I had an extremely hard time executing it, so I pivoted my project to this secondary concept at the last minute. However, I had a lot of fun creating it, as well as working on the styling and themes of the splash screens in particular. I hope you enjoy it!

sketch 52

//Jackie Chou
//jwchou@andrew.cmu.edu
//Section E
//Final Project

//stores image variables
var explosion;
var lost;
var crash;
var win;
var beginScreen;
var lightning;
var mountain;
var img;

//variable to determine if the game has started
var gameStarted = false;

//position and speed variables for the plane
var xPos = 240;
var yPos = 0;
var xSpeed = 0;
var ySpeed = 0;

//arrays to store the obstacles in
var mountains = [];
var lightnings = [];


function setup() {
    createCanvas(480, 480);
    //load background and obstacle images
    img = loadImage("https://i.imgur.com/x3rvhGU.png");
    lightning = loadImage("https://i.imgur.com/v6p1ANv.png");
    mountain = loadImage("https://i.imgur.com/tLB1n6D.png");
    explosion = loadImage("https://i.imgur.com/8J62X6Z.png");

    //load splash screens
    lost = loadImage("https://i.imgur.com/znFRmOW.png");
    crash = loadImage("https://i.imgur.com/TXv7bto.png");
    win = loadImage("https://i.imgur.com/T0qvSdh.png");
    beginScreen = loadImage("https://i.imgur.com/J34UN7I.png");
    //pushes random coordinates into the obstacle arrays
    for (i = 0; i < 8; i++) {
        lightnings.push(random(0, width));
        lightnings.push(random(80, 350));
        mountains.push(random(0, width));
        mountains.push(random(80, 350))
    }   
}

function draw() {
    imageMode(CENTER);
    //draws background image
    image(img, 240, 240);
    //initializes plane if the game has begun
    if (gameStarted == true){
        ySpeed = 0.5;
    }
    //controls plane's direction
    yPos += ySpeed; 
    xPos += xSpeed;
    //calls function to draw obstacles
    drawObstacles();
    //displays splash screen before the game starts
    if (gameStarted == false) {
        image(beginScreen, width/2, height/2);
    }
    //drawing the airplane
    fill(240);
    strokeWeight(0.5);
    //wings
    ellipse(xPos, yPos, 70, 11); 
    ellipse(xPos, yPos - 20, 35, 8);
    //horz stabilizer
    fill(108, 190, 225);
    ellipse(xPos, yPos, 17, 45); 
    //fuselage
    ellipse(xPos + 17, yPos + 5, 6, 15); 
    //left engine
    ellipse(xPos - 17, yPos + 5, 6, 15); 
    //right engine
    fill(0);
    ellipse(xPos - 17, yPos + 10, 10, 2); 
    //right propeler
    ellipse(xPos + 17, yPos + 10, 10, 2); 
    //left propeller
    fill(240);
    ellipse(xPos, yPos - 25, 5, 17); 
    //tail
    fill(0);
    beginShape(); 
    //cockpit
    vertex(xPos - 5, yPos + 10);
    vertex(xPos, yPos + 17);
    vertex(xPos + 5, yPos + 10);
    vertex(xPos + 5, yPos + 5);
    vertex(xPos, yPos + 10);
    vertex(xPos - 5, yPos + 5);
    vertex(xPos - 5,yPos +  10);
    endShape(); 
    //checks to see if the plane has collided into lightning
    for (i = 0; i < lightnings.length; i += 2) {
        if (dist(xPos, yPos, lightnings[i], lightnings[i+1]) <= 35) {
            gameOver();
        }   
    }
    //checks to see if the plane has collided in mountains
    for (i = 0; i < mountains.length; i += 2) {
        if (dist(xPos + 3, yPos, mountains[i], mountains[i+1]) <= 38) {
            gameOver();
        }   
    }
    //calls landing function if plane crosses top edge of runway
    if (dist(xPos, yPos, 235, 440) <= 15) {
        xSpeed = 0;
        ySpeed = 0;
        landed();
    }
    //calls lost screen function if plane leaves canvas (x)
    if (xPos <= 10 || xPos >= 470) {
        gotLost();
    }
    //calls lost screen function if plane leaves canvas (y)
    if (yPos >= 470) {
        gotLost();
    }
}

//draws the obstacles using randomized values from the arrays
function drawObstacles() {
    for (i = 0; i < lightnings.length; i += 2) {
        image(lightning, lightnings[i], lightnings[i+1]);
        //image(mountain, random(0, width), random(80, 350));
    }
    for (i = 0; i < mountains.length; i += 2) {
        image(mountain, mountains[i], mountains[i+1]);
    }
}

//controls the direction of the plane via arrow keys
function keyPressed() {
    if (keyCode === RIGHT_ARROW) {
        xSpeed = 0.65;
    }
    if (keyCode === LEFT_ARROW) {
        xSpeed = -0.65;
    }
    if (keyCode === DOWN_ARROW) {
        xSpeed = 0;
    }
}

//starts the game
function mousePressed() {
    gameStarted = true;
}

//game over function, displays splash screen
function gameOver() {
    image(explosion, xPos, yPos - 3);
    image(crash, width/2, height/2);
    noLoop();
}

//plane lost function
function gotLost() {
    image(lost, width/2, height/2);
    noLoop();
}

//plane landed function
function landed() {
    image(win, width/2, height/2);
    noLoop();
}

mstropka Final Project E (FIXED)

sketch

//Name: Max Stropkay
//Andrew ID: mstropka@andrew.cmu.edu
//Section: E
//Final Project

//decalare variables for font, and audio file
var avenir;
var littlewing;

//array to store vehicle objects
var vehicles = [];

//diameter of circles
var diameter;

//store the value of the amplitude of the audio file
var amplitude;

//array to store the strings that make up the lyrics
//of the song
var lyrics = ['little wing', 'well','shes','walking','through',
  'the','clouds','with a', 'circus', 'mind', 'thats','running', 'round',
  'butterflies', 'zebras', 'moonbeams', 'fairytales',
  'thats all', 'she ever', 'thinks about', 'riding with', 'the', 'wind', 'when',
  'Im sad', 'she comes', 'to me', 'with a', 'thousand', 'smiles', 'she',
  'gives to', 'me', 'free','its alright', 'she said', 'its alright', 'take',
  'anything', 'you', 'want', 'from me', 'anything'];

//array to store the times at which the lyrics
//should appear on screen
var times = [34000, 500, 500, 3000, 500, 500, 2000, 200, 300, 3000, 500,
  500, 3000, 1500, 1500, 2000, 3000, 3000, 300, 300, 300, 2000, 4000,
  500, 500, 3000, 500, 500, 2000, 200, 300, 3000, 500,
  500, 3000, 1500, 1500, 2000, 3000, 3000, 300, 300, 2000, 300, 18000];

var word = -1;

//load soundfile and font
function preload() {
  littlewing = loadSound('https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/Jimi-Hendrix-Little-Wing.mp3')
  avenir = loadFont("https://s3.us-east-2.amazonaws.com/maxstropkayfinalproject/AvenirNextLTPro-Demi.otf");
}

function setup() {
  createCanvas(1200, 480);
  //play audio file,set volume
  littlewing.play();
  littlewing.setVolume(0.5);
  //set value of amplitude to the amplitude of audio
  amplitude = new p5.Amplitude(.04);
  updateLyrics();

}

function draw() {
  background(51);

  //for every vehicle run behaviors, update, and show
  for (var i = 0; i < vehicles.length; i++){
    var v = vehicles[i];
    v.behaviors();
    v.update();
    v.show();
  }

  //set diameter to be determined by the amplitude
  var level = amplitude.getLevel();
  var volume = map(level, 0, 1, 0, 200);
  diameter = volume;
}

//define Vehicle object
  function Vehicle(x, y) {
    this.pos = createVector(random(0, width), random(0, height));
    this.target = createVector(x, y);
    this.vel = p5.Vector.random2D();
    this.acc = createVector();
    this.r = 10;
    this.color = 255;
    this.maxspeed = 10;
    this.maxforce = 0.5;
  }

  Vehicle.prototype.behaviors = function(f) {
    var arrive = this.arrive(this.target);
    this.applyForce(arrive);
  }

  Vehicle.prototype.applyForce = function(f) {
    this.acc.add(f);
  }
  //move vehicles based on attraction to the
  //target location
  Vehicle.prototype.update = function() {
    this.pos.add(this.vel);
    this.vel.add(this.acc);
    this.acc.mult(0);
    this.r = diameter + 10*(random(0,1));
    this.color = color(diameter*random(0, 100), diameter*random(0, 5), diameter*random(0, 10));
  }
  //draw ellipses at x,y coordinates of objects
  Vehicle.prototype.show = function() {
    noStroke();
    fill(this.color);
    ellipse(this.pos.x, this.pos.y, this.r, this.r);
  }
  //change speed of object as it gets closer to
  //its target location
  Vehicle.prototype.arrive = function(target) {
    var desired = p5.Vector.sub(target, this.pos);
    var d = desired.mag();
    var speed = this.maxspeed;
    if (d < 100){
      var speed = map(d, 0, 100, 0, this.maxspeed);
    }
    desired.setMag(speed);
    var steer = p5.Vector.sub(desired, this.vel);
    steer.limit(this.maxforce);
    return steer;

  }
  //move object toward its desired position
  Vehicle.prototype.seek = function(target) {
    var desired = p5.Vector.sub(target, this.pos);
    desired.setMag(this.maxspeed);
    var steer = p5.Vector.sub(desired, this.vel);
    steer.limit(this.maxforce);
    return steer;

  }

//display the next word in the array lyrics
//at the time from the time array
function updateLyrics(){
  vehicles = [];
  word = (word + 1) /*% lyrics.length*/;
  print(word);
  textAlign(CENTER);
  textFont("Avenir")
  var points = avenir.textToPoints(lyrics[word], 70, 300, 192);
  //console.log(points)

  for (var i = 0; i < points.length; i++){
    var pt = points[i];
    var vehicle = new Vehicle(pt.x, pt.y);
    vehicles.push(vehicle);
    // stroke(0,255,0);
    // strokeWeight(4);
    // point(pt.x, pt.y);
}
print(times[word]);
setTimeout(updateLyrics,times[word]);

}

For my final project, I made a program that generates dots that change size and color based on the volume of the music thats being played in the background. The dots then fly to form the lyrics in the song. Syncing up the timing of the lyrics and the music was harder and more time consuming than I anticipated, so it only is synced for the first verse.

Attached is the zip file that contains the audio and the font that can be run on a local server.

mstropka_Final Project_E

To run, first open terminal and copy and paste in this line of code

python -m SimpleHTTPServer 8000

This will run a local server. Then type into the URL in your browser

localhost:8000

Then navigate to wherever you downloaded the file and click to run it.

 

 

ctv Final Project

You are able to type in the box, click it to expand, and move the text box up and down!

sketch

var CONTAINERS;
var img;
var img2;
var img3;

function preload(){
    img = loadImage("https://i.imgur.com/SiATbai.png");
    img2 = loadImage("https://i.imgur.com/g9q8qO8.png");
    img3 = loadImage("https://i.imgur.com/zFUnlLi.png");
}

function setup() {
    createCanvas(800, 800);
    CONTAINERS = new aContainer();
}

function draw(){
    background('#165fa8');
    CONTAINERS.display();
}

//////Design and functionality of the text container
function aContainer() {
//////Properties for the individual container
  var state = 0;
  var txt = "";
  this.pos = 0;
  this.h = 100;
  this.color = color('#e2f0fb');
  this.shadow = 1;
  this.r = 20;
  this.txtSize = 34;

//////Save Button Dimensions
      var buttonX = 80;
      var buttonY = 40;
      var buttonX2 = 200;
      var buttonX3 = 500;
      var buttonW = 100;
      var buttonH = 40;

//////Execute the shapes and text when this is called,
//////Calls properties in the section right above
  this.display = function() {
        if(this.pos <= 0){this.pos = 0}
        if(this.pos >= 5){this.pos = 5}
        fill(this.color);
        strokeWeight(0);
        rect(80, this.pos*100+120, 640, this.h, this.r);
        fill(60);
        textSize(this.txtSize);
        textFont("Avenir");
        text(txt, 110, this.pos*100+180);
        fill(240);
        rect(buttonX, buttonY, buttonW, buttonH, 20);
        image(img, buttonX+buttonW/2-17.5, buttonY+2.5, 35, 35);
        rect(buttonX2, buttonY, buttonW, buttonH, 20);
        image(img2, buttonX2+buttonW/2-17.5, buttonY+2.5, 35, 35);
        rect(buttonX3, buttonY, buttonW, buttonH, 20);
        image(img3, buttonX3+buttonW/2-17.5, buttonY+2.5, 35, 35);
  }

//////Function is called when mouse is pressed
//////Only executes if cursor is over the container
  this.pressed = function() {
      if (mouseX > 80 & 
          mouseX < 720 && 
          mouseY > this.pos*100+120 && 
          mouseY < this.pos*100+this.h+120) {
          if(state%2 == 0){
              this.h = 500;
              state++;
          } else if(state%2 == 1){
              this.h = 100;
              state++;      
          }
     }
  }
//////Add the typed key to the string variable 'txt'
  this.keys = function(){
//////If text goes beyond specified width, put text on new line
      txt = txt + key;
      txtWid = textWidth(txt)%500;
      if(txtWid>475){
          txt+= "\n"
      }
//////If the enter key is pressed, put text on new line
      if(keyCode == 13){
          txt += "\n";
      }
//////Ability to delete a letter that is typed
        if(keyCode == 8 & txt.length>0){
            txt = txt.substring(0, txt.length - 2);
        }
  }
///////Adds abbility to press save button
  this.downButton = function(){
      if (mouseX > buttonX & 
          mouseX < buttonX + buttonW && 
          mouseY > buttonY && 
          mouseY < buttonY + buttonH) {
            this.pos++;
     } else if (mouseX > buttonX2 & 
          mouseX < buttonX2 + buttonW && 
          mouseY > buttonY && 
          mouseY < buttonY + buttonH) {
            this.pos--;
     }
  }
//////Make the text box larger
    this.expand = function(){
        if(this.h == 100){
        }
    }
}

function mousePressed(){
    CONTAINERS.pressed();  
    CONTAINERS.downButton();
}

function keyPressed() {
    CONTAINERS.keys();
}

 

 

elizabew-final project

Click on either of the two choices that are available to continue through the story.

(Try the closet route!)

sketch

//calls beginning function to start the game over
var scene = new beginning();

//holds background images
var bg = [];

var bgURL = [
  //outside image
  "https://i.imgur.com/NhThk6g.jpg",
  //lake reflection image
  "https://i.imgur.com/GA10Vet.jpg",
  //image of both lake and forest
  "https://i.imgur.com/c6C6zEC.jpg",
  //cat image
  "https://i.imgur.com/4zrzVTj.jpg",
  //true ending image
  "https://i.imgur.com/LADTQJI.jpg"];

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

function preload(){
  // load images from URL
  for (i = 0; i < bgURL.length; i++){
    bg.push(loadImage(bgURL[i]));
  }
}

//LIST OF SCENES
function beginning() {
  this.sentence = "You wake up surrounded by complete darkness." +
  " Your body aches and you hear the faint sound of growling behind you." +
  " You pull your red hood around yourself to keep warm." +
  " You feel around and find two doors." +
  " One with a round knob and one of with a square knob.";
  this.left = new sit1();
  this.right = new sitA();
  this.lefttext = "go through the round knobbed door";
  this.righttext = "go through the square knobbed door";
  this.fillcolor = "black";
}

//Round knobbed door
function sit1() {
  this.sentence = "You immediately begin to sprint out the door." +
  " The fresh air hits your face like cold knives. Outside." +
  " You look behind you to hear the growling rumble louder." +
  " She's waking up too.";
  this.left = new sit2();
  this.right = new death("You wait and see what happens." +
  " The beast begins to wake up and it immediately sees you" +
  " She's angry and you know exactly why." +
  " She leaps towards you in a familiar fashion," +
  " mouth wide open and ready to bite down...");
  this.lefttext = "RUN!!!!";
  this.righttext = "Wait and see what happens";
  this.fillcolor = "";
  this.b = "outside";
}

function sit2() {
  this.sentence = "You run away before the beast could notice you leaving." +
  " You see a forest and a lake in the distance";
  this.left = new sitOne();
  this.right = new sit3();
  this.lefttext = "Run towards the forest";
  this.righttext = "Run towards the lake";
  this.fillcolor = "";
  this.b = "treeAndLake"
}

function sit3() {
  this.sentence = "As you run towards the lake," +
  " you stop by the edge of the water," +
  " mesmorized by your own unrecognizable reflection...";
  this.left = new death("You can't help but continue staring at yourself." +
  " Bright blue eyes and a long red cape embracing your frail body." +
  " You hear growling beghind you... GIVE...IT...BACK.... ");
  this.right = new sitThree();
  this.lefttext = "Keep staring at your own reflection";
  this.righttext = "Pull your eyes away and continue running";
  this.fillcolor = "";
  this.b = "reflection"
}

function sitOne(){
  this.sentence = "Start running faster and faster through the forest," +
  " trees flashing past you." +
  " You hear the growling not too far behind...";
  this.left = new death("You climbed up the tree as fast as you could." +
  " Right as you grabbed a second branch," +
  " you feel your hood getting tugged, pulling you down with it...");
  this.right = new sitTwo();
  this.lefttext = "Climb up a tree";
  this.righttext = "Hide in the bushes";
  this.fillcolor = "flashing green";
}

function sitTwo(){
  this.sentence = "You jump into a nearby bush and wait..." +
  " the sound of a frustrated growling felt close," +
  " but it seems to have disappeared now.";
  this.left = new sitThree();
  this.right = new sit3();
  this.lefttext = "Keep running!";
  this.righttext = "Run back towards the lake";
  this.fillcolor = "";
  this.b = "outside";
}

function sitThree(){
  this.sentence = "You decide to keep running." +
  " As you run you trip over a soft rock." +
  " Wait, that's a cat!";
  this.left = new sitFour();
  this.right = new sitFour();
  this.lefttext = "Pet the cat";
  this.righttext = "Scratch the cat's belly";
  this.fillcolor = "";
  this.b = "cat";
}

function sitFour(){
  this.sentence = "The cat purrs and rolls around on the ground." +
  " After a few minutes it gets up.";
  this.left = new sitneutralending();
  this.right = new sitneutralending();
  this.lefttext = "Follow the cat";
  this.righttext = "Why wouldn't you follow this cat?";
  this.fillcolor = "";
  this.b = "cat";
}

//Neutral ending
function sitneutralending(){
  this.sentence = "(Neutral ending) You follow the cat into a small den." +
  " I guess this is a nicer ending."
  this.lefttext = "";
  this.righttext = "";
  this.fillcolor = "";
  this.b = "outside";
}

//--------------------
//Square knobbed door
function sitA() {
  this.sentence = "You open the door and find yourself looking into a closet." +
  " You run in and shut the door as quietly as you can." +
  " She's awake now too.";
  this.left = new sitB();
  this.right = new death("You decided to scream on the top of your lungs." +
  " Immediately and without warning, the beast breaks through the closet" +
  " door. Did you have a death wish?");
  this.lefttext = "Stay quiet and hope she leaves";
  this.righttext = "SCREAM!!!";
  this.fillcolor = "black";
}

//Closet scene
function sitB() {
  this.sentence = "You decide to sit quietly in the closet." +
  " After what seemed like hours, the growling disappeared...";
  this.left = new sitC();
  this.right = new sit1A();
  this.lefttext = "Stay in the closet";
  this.righttext = "Walk out";
  this.fillcolor = "black";
}

function sitC() {
  this.sentence = "You felt uneasy and decided to stay in the closet." +
  " You lean back onto the back of the closet and surprisingly," +
  " you fell into a hole that leads outside!";
  this.left = new sitD();
  this.right = new sit1A();
  this.lefttext = "Stay in the closet";
  this.righttext = "Crawl outside";
  this.fillcolor = "black";
}

function sitD(){
  this.sentence = "You STILL decide to stay in the closet for some reason." +
  " Maybe you're still feeling uneasy..." +
  " Time continues to pass as it usually does."+
  " Are you even going to continue on this journey?";
  this.left = new sitE();
  this.right = new sit1A();
  this.lefttext = "Stay in the closet";
  this.righttext = "CRAWL OUTSIDE";
  this.fillcolor = "black";
}

function sitE(){
  this.sentence = "You still stay in the closet. This is not like the narnia" +
  " wardrobe. There is nothing special about this closet." +
  " Why do you want to stay in here so badly?";
  this.left = new sitF();
  this.right = new sit1A();
  this.lefttext = "Stay in the closet";
  this.righttext = "Crawl. Outside. Now.";
  this.fillcolor = "black";
}

function sitF(){
  this.sentence = "Okay, you've committed, we'll stay in this dumb closet."+
  " I even took away the 'crawl outside' button. I hope you're happy with yourself.";
  this.left = new sitG();
  this.right = new sitG();
  this.lefttext = "Stay in the closet";
  this.righttext = "Stay in the closet";
  this.fillcolor = "black";
}

function sitG(){
  this.sentence = "I bet you're happy about this endless loop,"+
  " Even if you change your mind you won't get it back, you're gonna have to" +
  " refresh this whole game manually.";
  this.left = new sitH();
  this.right = new sitH();
  this.lefttext = "Stay in the closet";
  this.righttext = "Stay in the closet";
  this.fillcolor = "black";
}

function sitH(){
  this.sentence = "...";
  this.left = new sitI();
  this.right = new sitI();
  this.lefttext = "Stay in the closet";
  this.righttext = "Stay in the closet";
  this.fillcolor = "black";
}

function sitI(){
  this.sentence = "..........";
  this.left = new sitJ();
  this.right = new sitJ();
  this.lefttext = "Stay in the closet";
  this.righttext = "Stay in the closet";
  this.fillcolor = "black";
}

function sitJ(){
  this.sentence = "..................";
  this.left = new sitK();
  this.right = new sitK();
  this.lefttext = "Stay in the closet";
  this.righttext = "Stay in the closet";
  this.fillcolor = "black";
}

function sitK(){
  this.sentence = "Okay, I'm just going to push you outside. Shoo!";
  this.left = new sit1A();
  this.right = new sit1A();
  this.lefttext = "OUTSIDE";
  this.righttext = "GO. OUTSIDE.";
  this.fillcolor = "black";
}

//To grandmothers house we go!
function sit1A(){
  this.sentence = "You walk outside to see the beast far off in the distance," +
  " obviously looking for you. But you have other plans...";
  this.left = new death("You dance(?) towards the beast flailing about,"+
  " probably hoping to get eaten. (I bet you were the same person wanting to" +
  " stay in that closet...)");
  this.right = new sit1B();
  this.lefttext = "Ignore your plans and dance towards the beast";
  this.righttext = "Head towards the smoke in the nearby forest";
  this.fillcolor = "";
  this.b = "outside";
}

function sit1B(){
  this.sentence = "You run through the forest, to grandmother's house." +
  " She'll protect you from the beast. You hear the beast" +
  " catching up to you, desperate to get what you've stolen back..." +
  " You notice that there is a large pit nearby";
  this.left = new sit1C();
  this.right = new goodishending();
  this.lefttext = "Continue running towards grandmother's house";
  this.righttext = "Wait to push the wolf into the pit";
  this.fillcolor = "flashing green";
}

function sit1C(){
  this.sentence = "You finally reach the door of the house" +
  " The beast is not far behing you. 'GRANDMOTHER' you scream, let me in!" +
  " Hurry!!";
  this.left = new trueending();
  this.right = new death("You decide to keep running, but the beast gets to you." +
  " And you were so close too!");
  this.lefttext = "Wait for grandmother to open the door";
  this.righttext = "Keep running!";
  this.fillcolor = "";
  this.b = "outside";
}

//True ending
function trueending(){
  this.sentence = "(True Ending) Soon after, the door opens." +
  " It's almost impossible to hide your grin..." +
  " You look back at the girl in wolfs skin that was chasing you," +
  " desperate to get her hood back." +
  " 'My, what big teeth you have, little riding hood'!";
  this.lefttext = "";
  this.righttext = "";
  this.fillcolor = "";
  this.b = "trueEnd";
}

//Death scene when the beast gets you
function death(sentence) {
  this.sentence = sentence;
  this.lefttext = "";
  this.righttext = "";
  this.fillcolor = "red";
}

//Good ending where you kill the beast
function goodishending(){
  this.sentence = "(Good Ending) You push the wolf into the pit. Hooray!" +
  " Now nothing is in your way...";
  this.lefttext = "";
  this.righttext = "";
  this.fillcolor = "";
  this.b = "outside";
}

function draw() {

  //Determining background color
  if (scene.fillcolor == "red"){
    background(171,6,11);
  }
  else if (scene.fillcolor == "blue"){
    background(0, 6, 34);
  }
  else if (scene.fillcolor == "flashing green"){
    frameRate(8);
    var r = random(0, 8);
    var g = random(0, 60);
    var b = random(0, 5);
    background(r, g, b);
  }
  else if (scene.fillcolor == "green"){
    background(2, 26, 8);
  }
  else if (scene.fillcolor == "black"){
    background(0);
  }
  else {
    background(0);
  }

  //Creates background images
  if (scene.b == "outside"){
    image(bg[0], 0, 0, 480, 450);
  }
  if (scene.b == "reflection"){
    image(bg[1], 0, 0, 480, 450);
  }
  if (scene.b == "treeAndLake"){
    image(bg[2], 0, 0, 480, 450);
  }
  if (scene.b == "cat"){
    image(bg[3], 0, 0, 480, 450);
  }
  if (scene.b == "trueEnd"){
    image(bg[4], 0, 0, 480, 450);
  }


  //Story text details
  fill(200);
  textSize(12);
  text(scene.sentence, 50, 270, 380, 80);
  //left text decision
  text(scene.lefttext, 50, 380, 100);
  //right text decision
  text(scene.righttext, 300, 380, 100);

  //Reset button text
  if (scene.lefttext == "") {
    text("click here to start over", 180, 370);
  }


}

//Creating "buttons" for choices and for reset
function mouseClicked(){

  //Reset button
  if (scene.lefttext == "") {
    if (mouseX > 180 & mouseX < 300 && mouseY > 360 && mouseY < 380){
       //resets game
       scene = new beginning();
    }
  }

 else{
   //left button decision
   if (mouseX > 50 & mouseX < 130 && mouseY > 370 && mouseY < 420){
     scene = scene.left;
   }
   //right button decision
   if (mouseX > 300 & mouseX < 440 && mouseY > 370 && mouseY < 420){
     scene = scene.right;
   }
 }

}

I decided to create a choose-your-own-adventure game! My initial idea was to focus on having no visuals—using only text and sound to guide the user through the story—but ultimately ended up using both visuals and text together, and just text on its own.

The story was difficult to write in its own right and I don’t claim that it is that good, but the point of this game is that most of the endings the user runs into will build on the story of the game. I decided to focus mainly on using objects (since that was the most difficult part of this class for me and I wanted to make sure I ended this class with the knowledge of how to use them).

gyueunp – Final Project

Final Project

/*
* GyuEun Park
* 15-104 E
* gyueunp@andrew.cmu.edu
* Final Project
*/

var dots = []; //array of dots in beginning scene
var gravity;
var stars = []; //array of stars in ending scene
var speed;
var ismoving = true;

function setup() {
    createCanvas(600, 600);
    background(14, 94, 96);

    //turtle for the center of the transition scene 
    var turtle = makeTurtle(width - 115, height - 455);
    turtle.penDown();
    turtle.setColor(0);
    for (var i = 0; i < 1300; i++) {
        turtle.forward(10);
        turtle.right(141.5);
        turtle.forward(420);
        if (i % 20 === 0) {
            turtle.forward(70);
        }
    }
    if (ismoving){
        //dots jump up relatively high due to gravity
        gravity = createVector(0, 0.2);
        fill(16, 198, 216, 100);
        stroke(186, 198, 216, 200);
        strokeWeight(4);
    }
    else {
        //array of stars up to 2000
    for (var i = 0; i < 2000; i++) {
    stars[i] = new Star();
    }
  }
}

function draw() {
    if (ismoving) {
        //drawing jumping dots in the initial scene
        background(1, 11, 28, 50);
        if (random(1) < 0.2) {
            dots.push(new Dots());
        }
        //push through the array of dots, update and show them
        for (var i = 0; i < dots.length; i++) {
            dots[i].update();
            dots[i].show();
        }
    }
    else {
        background(1, 11, 28, 10);
        //the lower the cursor, the slower the star movement 
        speed = map(mouseY, 10, width / 2, 0, 5);
        //translate so that stars moving out from center, not top left 
        translate(width / 2, height / 2);
        for (var i = 0; i < stars.length; i++) {
            //update and show stars that are in motion
            stars[i].update();
            stars[i].show();
        }
    }
}


//dot constructor function
function Dots() {
    this.dots = new Particle(random(width), height);
    this.update = function() {
        this.dots.applyForce(gravity);
        this.dots.update();
    }
    this.show = function() {
        this.dots.show();
    }
}



//particle constructor function
function Particle(x,y) {
    this.pos = createVector(x,y);
    this.vel = createVector(0, random(-15, -5));
    this.acc = createVector(0, 0);

    this.applyForce = function(force){
        //add force to acceleration, force accumulation
        this.acc.add(force);
    }

    this.update = function() {
        //take the acceleration and adds it to the velocity
        this.vel.add(this.acc);
        //take the velocity and adds it to the position
        this.pos.add(this.vel);
        //multiply acc to 0 so that acc starts with 0 
        this.acc.mult(0);
    }

    this.show = function() {
        point(this.pos.x, this.pos.y);
    }
}

//star details in the transitioned scene
function Star() {
  this.x = random(-width, width);
  this.y = random(-height, height);
  this.z = random(width);
  this.pz = this.z;

  this.update = function() {
    this.z = this.z - speed;
    if (this.z < 1) {
      this.z = width;
      this.x = random(-width, width);
      this.y = random(-height, height);
      this.pz = this.z;
    }
  }

  this.show = function() {
    fill(16, 198, 216, random(200));
    noStroke();

    //the locations of the stars, dispersed across the canvas
    var sx = map(this.x / this.z, 0, 4, 0, width);
    var sy = map(this.y / this.z, 0, 3, 0, height);

    //when closer bigger, when farther smaller in size
    var r = map(this.z, 0, width, 16, 0);
    ellipse(sx, sy, r, r);

  }
}

function mousePressed(){
    ismoving = !(ismoving);
    setup();
}

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

Instructions: Click anywhere or move your cursor around to make alterations.

Brief summary: Jumping Dots, Turtle, and Turquoise Starfield.

For my final project, I took the advantage of making my canvas a space in which the viewers could momentarily be immersed in. As I believe that the  strength of interactive artworks is their ability to allow the audiences to create unexpected changes, I allowed the environment of my work to be altered by the viewers. Despite the changeable environment, however, I also focused on achieving a sense of visual consistency through the usage of coherent colorations and forms.

Conflicting factors coexist in my work; the space is chaotic yet orderly, inviting yet daunting, random yet systematic. Coexistences such as these were merged in creating this single work. I hope you enjoy momentarily being immersed in this space I created!

I also filmed projections of my work to experience its amplified effects outside of my screen.

and here are screenshots of various possible outcomes:

Here is a video of a slight alteration of the piece. I liked how it looked (and reminded me of Christmas and our imminent winter break!), so I decided to include it.

Final Project Thomas Wrabetz / Anna Boyle

sketch

//Anna Boyle and Thomas Wrabetz
//Main functions

//Thomas' code
function setup() {
    createCanvas(480, 480);
    rectMode( CENTER );
    player = makePlayer( width / 2, height / 2 );
    level = makeLevel();
    var sec=second();
}

function draw() {
    background(200);
    player.draw();
    player.step();
    level.draw();

//Anna's code
    fill(0);
    txt=width/2
    fill(255);
    noStroke();
    if (drawBubble==1){
//triangle for speech bubble
    triangle(width/2-20, txtH+20, bubbleX, bubbleY, width/2+20, txtH+20)
//if the player is on the top half, make the bubble on the bottom half
    if (player.y<height/2){
      txtH=440;
      rect(width/2, 470, width, bubbleHeight);
//adjust the line height when there is only one line
      singleLineHeight=465;
//if the player is on the bottom half, make the bubble on the top half
    }if (player.y>=height/2){
      txtH=30;
      rect(width/2, 20, width, bubbleHeight);
//adjust the line height when there is only one line
      singleLineHeight=30;
  }
    fill(0);
//makes the quote
    textSize(17);
    textAlign(CENTER);
    printQuote( whichQuote );
  }
    rectMode(CORNER);
//draws the inspiration meter red bar
    fill(188, 64, 64);
    rect(width-20, 0, 20, height);
//draws the inspiration meter's variable green bar
    fill(64, 188, 64);
    rect(width-20, height-inspiroMeter, 20, height);
    rectMode(CENTER);
//if the player gets enough quotes, they will win and see this screen
    if (inspiroMeter>480){
      fill(255);
      rect(width/2, height/2, width, height)
      fill(0);
      textSize(32)
      text("CONGRATULATIONS!", width/2, height/2-25);
      text("YOU ARE INSPIRED", width/2, height/2+25);
      noLoop();
    }
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Player object

//-----PLAYER OBJECT-----//

var PSIZE = 30;
var PCOLOR = [ 25, 150, 25, 255 ];
var PSPEED = 3;
var keyArray = [];

//Updates the player's position based on keyboard input
function stepPlayer()
{
    //Variables to track the player's movement in each direction
    var yStep = 0;
    var xStep = 0;
    if( keyIsPressed )
    {
        for( var i = 0; i < keyArray.length; i++ )
        {
            switch( keyArray[i] )
            {
                case 'W':
                    yStep -= PSPEED;
                    break;
                case 'S':
                    yStep += PSPEED;
                    break;
                case 'A':
                    xStep -= PSPEED;
                    break;
                case 'D':
                    xStep += PSPEED;
                    break;
            }
        }
        //Adjust speed for diagonal movement
        if( xStep != 0 & yStep != 0 )
        {
            xStep *= 0.7071
            yStep *= 0.7071
        }
        //Check if the player will collide with a wall in the x-direction
        //and move the player if not
        if( !level.collisionSearch( this.x + xStep, this.y, PSIZE ) )
        {
            //If the player is too close to the edges of the screen,
            //move the level instead of the player
            if( ( this.x < width * 4/5 || xStep < 0 ) 
                && ( this.x > width * 1/5 || xStep > 0 ) ) this.x += xStep;
            else level.xOffset -= xStep;
        }
        //Check if the player will collide with a wall in the y-direction
        //and move the player if not
        if( !level.collisionSearch( this.x, this.y + yStep, PSIZE ) )
        {
            //If the player is too close to the edges of the screen,
            //move the level instead of the player
            if( ( this.y < height * 4/5 || yStep < 0 ) 
                & ( this.y > height * 1/5 || yStep > 0 ) ) this.y += yStep;
            else level.yOffset -= yStep;
        }
        //If the player collides with a figure, update the bubble
        var figure = level.figureCollisionSearch( this.x + xStep, 
                                                  this.y + yStep, PSIZE );
        if( figure != -1 )
        {
            if( !drawBubble )
            {
                drawBubble = true;
                //Only update to a new quote if this is a different figure
                if( bubbleID != level.figures[ figure ].ID )
                {
                    bubbleID = level.figures[ figure ].ID;
                    updateBubble();
                }
            }
            bubbleX = level.figures[ figure ].x + level.xOffset;
            bubbleY = level.figures[ figure ].y + level.yOffset;
        }
        else if( drawBubble )
            drawBubble = false;
        level.step();
    }
}

//Draw the player
function drawPlayer()
{
    fill( PCOLOR );
    rect( this.x, this.y, PSIZE, PSIZE );
}

function makePlayer( px, py )
{
    player = { x: px, y: py, draw: drawPlayer, step: stepPlayer };
    return player;
}

//-----KEY TRACKING-----//

//Each key pressed is stored in the key array
function keyPressed()
{
    keyArray.push( key );
}

//Keys are removed from the key array when released
function keyReleased()
{
    for( var i = 0; i < keyArray.length; i++ )
    {
        if( keyArray[i] == key ) keyArray.splice( i, 1 );
    }
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Walls and level and figures

//-----INSPIRATIONAL FIGURE OBJECT-----//

figureColorArray = [ "Red", "Blue", "Green", "Yellow",
                     "Purple", "Orange", "Brown" ];
//Counter to give the figures unique IDs
figureIDCounter = 0;
//Counter that keeps track of how many open spaces have been created
figureCounter = 0;
//Each time figureCounter reaches FIGUREFREQ, a new figure is created
FIGUREFREQ = 10;
//Size of a figure
FIGUREWIDTH = 30;

function makeFigure( xPos, yPos )
{
    figure = { x: xPos, y: yPos, figureColor: random(figureColorArray),
               ID: figureIDCounter };
    figureIDCounter++;
    return figure;
}


//-----WALL OBJECT-----//

//Size of a wall
var WALLWIDTH = 80;
var WALLCOLOR = [ 116, 18, 229, 255 ];
var WALLCOLORDARK = [ 39, 7, 76, 255 ];

function makeWall( wx, wy )
{
    var wall = { x: wx, y: wy, pattern: makePattern() };
    return wall;
}

//-----LEVEL OBJECT-----//

//Add a row to the level. The parameters indicate which side
function levelAddRow( xRef, yRef )
{
    //Variables to track whether the new row is an empty row
    //and whether it has intersected an existing corridor
    var before = false;
    var after = false;
    var passed = false;
    var justPassed = false;
    //Left Side
    if( xRef == 1 ) 
    {
        //Clear out old row on opposite side
        this.walls.unshift( [] );
        this.walls.splice( this.walls.length - 1, 1 );
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls[1].length-2; i++ )
        {
            if( this.walls[1][i] == 0 & this.walls[1][i+1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls[1].length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[1][i] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[1][i] == 0 & i != 0 && this.walls[1][i-1] != 0 &&
                  i != this.walls[1].length - 1 && this.walls[1][i+1] != 0 ) ||
                ( before && ( !passed || justPassed ) ) || ( after && passed ))
            {
                this.walls[0][i] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( -1 * WALLWIDTH,
                                       (i - 1) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else this.walls[0][i] = makeWall( -1 * WALLWIDTH, 
                                              (i - 1) * WALLWIDTH );
            justPassed = false;
        }
    }
    //Right Side
    if( xRef == -1 ) 
    {
        //Clear out old row on opposite side
        this.walls.push( [] );
        this.walls.shift( 1 );
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls[1].length-2; i++ )
        {
            if( this.walls[this.walls.length-2][i] == 0 
                & this.walls[this.walls.length-2][i+1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls[this.walls.length-2].length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[this.walls.length-2][i] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[this.walls.length-2][i] == 0 & i != 0 &&
                this.walls[this.walls.length-2][i-1] != 0 && 
                i != this.walls[this.walls.length-2].length - 1 &&
                this.walls[this.walls.length-2][i+1] != 0 ) ||
                ( before && (!passed || justPassed) ) || ( after && passed ) )
            {
                this.walls[this.walls.length-1][i] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (this.walls.length-2) 
                                                   * WALLWIDTH, 
                                                   (i-1) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else this.walls[this.walls.length-1][i] = 
                 makeWall( (this.walls.length-2) 
                           * WALLWIDTH, (i-1) * WALLWIDTH );
            justPassed = false;
        }
    }
    //Top
    if( yRef == 1 )
    {
        //Clear out old row on opposite side
        for( i = 0; i < this.walls.length; i++ )
        {
            this.walls[i].unshift( -1 );
            this.walls[i].splice( this.walls[i].length - 1, 1 );
        }
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls.length-2; i++ )
        {
            if( this.walls[i][1] == 0 & this.walls[i+1][1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls.length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[i][1] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[i][1] == 0 & i != 0 && this.walls[i-1][1] != 0 
                  && i != this.walls.length - 1 
                  && this.walls[i+1][1] != 0 ) 
                  || (before && (!passed || justPassed)) || (after && passed))
            {
                this.walls[i][0] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (i-1) * WALLWIDTH,
                                       -1 * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else 
                this.walls[i][0] = makeWall((i-1) * WALLWIDTH, -1 * WALLWIDTH);
            justPassed = false;
        }
    }
    //Bottom
    if( yRef == -1 )
    {
        //Clear out old row on opposite side
        for( i = 0; i < this.walls.length; i++ )
        {
            this.walls[i].push( -1 );
            this.walls[i].shift( 1 );
        }
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls.length-2; i++ )
        {
            if( this.walls[i][this.walls.length-2] == 0 
                & this.walls[i+1][this.walls.length-2] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls.length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[i][this.walls[0].length-2] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[i][this.walls[0].length-2] == 0 & i != 0 
                  && this.walls[i-1][this.walls[0].length-2] != 0 
                  && i != this.walls.length - 1 
                  && this.walls[i+1][this.walls[0].length-2] != 0 ) 
                  || (before && (!passed || justPassed)) || (after && passed)) 
            {
                this.walls[i][this.walls[0].length-1] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (i-1) * WALLWIDTH,
                                      (this.walls[0].length-2) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else 
                this.walls[i][this.walls[0].length-1] = 
                makeWall( (i-1) * WALLWIDTH,
                          (this.walls[0].length-2) * WALLWIDTH );
            justPassed = false;
        }
    }
}

//Update the level, moving objects inside and adding new rows if needed
function levelStep()
{
    //If the offset for the walls is greater than the width of a wall,
    //Shift the array of walls and add a new row
    if( abs( this.xOffset ) >= WALLWIDTH )
    {
        //Incorporate offset into walls' basic x-positions
        for( var j = 0; j < this.walls.length; j++ )
        {
            for( var k = 0; k < this.walls[j].length; k++ )
            {
                if( this.xOffset > 0 )
                {
                    this.walls[j][k].x += WALLWIDTH;
                }
                if( this.xOffset < 0 )
                {
                    this.walls[j][k].x -= WALLWIDTH;
                }
            }
        }
        //Incorporate offset into figures' basic x-positions
        for( var j = 0; j < this.figures.length; j++ )
        {
            if( this.xOffset > 0 )
            {
                this.figures[j].x += WALLWIDTH;
            }
            if( this.xOffset < 0 )
            {
                this.figures[j].x -= WALLWIDTH;
            }
            //Remove figures that are off the screen
            if( this.figures[j].x > width + FIGUREWIDTH / 2 
                || this.figures[j].x < 0 - FIGUREWIDTH / 2 )
            {
                this.figures.splice( j, 1 );
                j--;
            }
        }
        //Reset the offset and add a new row
        if( this.xOffset > 0 )
        {
            this.xOffset -= WALLWIDTH;
            this.addRow( 1, 0 );
        }
        if( this.xOffset < 0 )
        {
            this.xOffset += WALLWIDTH;
            this.addRow( -1, 0 );
        }
    }
    if( abs( this.yOffset ) >= WALLWIDTH )
    {
        //Incorporate offset into walls' basic y-positions
        for( var j = 0; j < this.walls.length; j++ )
        {
            for( var k = 0; k < this.walls[j].length; k++ )
            {
                if( this.yOffset > 0 )
                {
                    this.walls[j][k].y += WALLWIDTH;
                }
                if( this.yOffset < 0 )
                {
                    this.walls[j][k].y -= WALLWIDTH;
                }
            }
        }
        //Incorporate offset into figures' basic y-positions
        for( var j = 0; j < this.figures.length; j++ )
        {
            if( this.yOffset > 0 )
            {
                this.figures[j].y += WALLWIDTH;
            }
            if( this.yOffset < 0 )
            {
                this.figures[j].y -= WALLWIDTH;
            }
            //Remove figures that are off the screen
            if( this.figures[j].y > height + FIGUREWIDTH / 2 
                || this.figures[j].y < 0 - FIGUREWIDTH / 2 )
            {
                this.figures.splice( j, 1 );
                j--;
            }
        }
        //Reset the offset and add a new row
        if( this.yOffset > 0 )
        {
            this.yOffset -= WALLWIDTH;
            this.addRow( 0, 1 );
        }
        if( this.yOffset < 0 )
        {
            this.yOffset += WALLWIDTH;
            this.addRow( 0, -1 );
        }
    }
}

//Checks if a square at x,y with size size would collide with the wall
//at index a,b of the array of walls
function levelWallCollision( x, y, size, a, b )
{
    var wall = this.walls[a][b];
    if( wall == 0 ) return false;
    return abs( x - ( wall.x + this.xOffset ) ) < size / 2 + WALLWIDTH / 2 
           & abs( y - ( wall.y + this.yOffset ) ) < size / 2 + WALLWIDTH / 2;
}

//Check collision for all the walls
function levelCollisionSearch( x, y, size )
{
    for( i = 0; i < this.walls.length; i++ )
    {
        for( j = 0; j < this.walls[i].length; j++ )
        {
            if( this.wallCollision( x, y, size, i, j ) ) return true;
        }
    }
    return false;
}

//Draw the wall at index a,b of the wall array
function levelDrawWall( a, b )
{
    var wall = this.walls[a][b];
    if( wall == 0 ) return;
    push();
    stroke( WALLCOLORDARK );
    fill( WALLCOLOR );
    rect( wall.x + this.xOffset, wall.y + this.yOffset, WALLWIDTH, WALLWIDTH );
    wall.pattern.draw( wall.x + this.xOffset, wall.y + this.yOffset );
    pop();
}

//Checks if a square at x,y with size size would collide with a figure
//at index a of the figure array
function levelFigureCollision( x, y, size, a )
{
    if( a >= this.figures.length ) return false;
    var figure = this.figures[a];
    return abs( x - ( figure.x + this.xOffset ) ) < size / 2 + FIGUREWIDTH / 2
                & abs( y - ( figure.y + this.yOffset ) ) 
                   < size / 2 + FIGUREWIDTH / 2;
}

//Check collision for all the figures. If found, returns the index of
//the colliding figure in the figure array. If not, returns -1.
function levelFigureCollisionSearch( x, y, size )
{
    for( i = 0; i < this.figures.length; i++ )
    {
        if( this.figureCollision( x, y, size, i ) ) return i;
    }
    return -1;
}

//Draw the figure at index a of the figure array
function levelDrawFigure( a )
{
    var figure = this.figures[a];
    if( figure == 0 ) return;
    push();
    stroke( 0 );
    fill( figure.figureColor );
    ellipse( figure.x + this.xOffset, figure.y + this.yOffset,
             FIGUREWIDTH, FIGUREWIDTH );
    pop();
}

//Draw all the walls and figures
function levelDraw()
{
    for( i = 0; i < this.walls.length; i++ )
    {
        for( j = 0; j < this.walls[i].length; j++ )
        {
            this.drawWall( i, j );
        }
    }
    for( i = 0; i < this.figures.length; i++ )
    {
        this.drawFigure( i );
    }
}

//Make a level, which contains arrays of walls and figures as well as a shared
//x and y offet which applies to every object in the level
function makeLevel()
{
    var wallsArray = [];
    var figuresArray = [];
    for( i = 0; (i - 1) * WALLWIDTH <= width + WALLWIDTH; i++ )
    {
        wallsArray.push( [] );
        for( j = 0; (j - 1) * WALLWIDTH <= height + WALLWIDTH; j++ )
        {
            if( i == 4 || j == 4 ) wallsArray[i].push( 0 );
            else 
                wallsArray[i].push( makeWall( (i - 1) * WALLWIDTH,
                                    (j - 1) * WALLWIDTH ) );
        }
    }
    level = { walls: wallsArray, figures: figuresArray, xOffset: 0, yOffset: 0,
              draw: levelDraw, drawWall: levelDrawWall,
              wallCollision: levelWallCollision,
              collisionSearch: levelCollisionSearch,
              step: levelStep, addRow: levelAddRow,
              drawFigure: levelDrawFigure, 
              figureCollision: levelFigureCollision,
              figureCollisionSearch: levelFigureCollisionSearch };
    return level;
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Pattern object for wall blocks

var DOTSIZE = 3;
var colors = [ [66,134,234,255], [23,216,213,255],
               [23,216,236,255], [68,216,23,255], [228,242,42,255] ];

function makePattern() {
    var angle;
    var newPattern={c: random(colors), arms: int( random( 4 ) ) + 2, 
                    a: random(2*PI), draw: drawPattern, dotPositionArray: [] };
    for( var i = 0; i < newPattern.arms; i++ )
    {
        for( var j = 0; j < WALLWIDTH / 2 - 5; j+= DOTSIZE * 2 )
        {
            angle = newPattern.a + i * (2 * PI / newPattern.arms);
            newPattern.dotPositionArray.push( j * cos( angle ) + 
                     ( sin( j ) * 20 * cos( angle + PI / 2 ) ) );
            newPattern.dotPositionArray.push( j * sin( angle ) + 
                     ( sin( j ) * 20 * sin( angle + PI / 2 ) ) );
        }
    }
    return newPattern;
}

function drawPattern( x, y ){
    fill(this.c)
    push();
    noStroke();
    var currentX;
    var currentY;
    for( var i = 0; i < this.dotPositionArray.length - 1; i+= 2 )
    {
            ellipse( x + this.dotPositionArray[i], y + this.dotPositionArray[i+1],
                     DOTSIZE, DOTSIZE );
    }
    pop();
}

//Anna Boyle
//Section D
//aboyle@andrew.cmu.edu
//Quote generator

var abstractNouns = ["Rebellion", "Curiosity", "Jealousy", "Friendship",
"Family", "Evil", "Life", "Hope", "Grace", "Love", "Faith", "Opportunity",
"Dedication", "Insanity", "Fortune", "Luck", "Hatred", "Knowledge", "Pain",
 "Heaven"];
var inspireNouns = ["rainbow", "cloud", "light", "star", "candle", "child",
"dream", "building", "hero", "breeze", "eye", "moon", "snowflake", "apple",
"tree", "flower", "butterfly", "mirror", "door", "heart"];
var inspireNounsPlural = ["rainbows", "clouds", "lights", "stars", "candles",
"children", "kisses", "buildings", "hands", "brothers", "sisters", 
"snowflakes", "dreams", "apples", "trees", "flowers", "butterflies", "mirrors",
"doors", "hearts"];
var strangeNouns=["peach cobbler", "deodorant", "used tissue", "conch shell",
"toaster", "pasta strainer", "blade of grass", "grandma's house", "unicycle",
"weed whacker", "shampoo bottle", "corpse", "snickerdoodle",
"ten gallon hat", "toupee", "colony of termites", "mother-in-law",
"sexy firemen calendar", "underground bunker", "angry baboon"];
var strangeNounsPlural = ["alien invasions", "clowns", "podiatrists",
"belly dancers", "cacti", "voodoo dolls", "raspberries", "dust bunnies",
"distant relatives", "kentucky fried chicken", "rotten eggs", "nudists",
"nunchuks", "toenail clippings", "rocket scientists", "green beans", "nuns",
"croissants", "drunk ballerinas", "shoelaces" ];
var inspireVerbs= ["flies", "moves", "shines", "waits", "stands", "goes",
"sleeps", "thinks", "cries", "laughs", "yells", "watches", "jumps"];
var inspireVerbsObj = ["hold", "hug", "love", "hate", "grab", "accept",
"support", "look at", "want", "sacrifice", "kiss", "pray for", "abandon"];
var inspireVerbsGerund= ["flying", "moving", "doing", "waiting", "standing",
"going", "saying", "thinking", "crying", "laughing", "yelling", "watching",
"jumping"];
var inspireVerbsObjGerund = ["holding", "hugging", "loving", "hating",
"grabbing", "accepting", "supporting", "seeing", "wanting", "finding",
"kissing", "praying for", "abandoning"];
var strangeVerbs=["dances", "dies", "melts", "yodels", "sneezes", "does yoga",
"crawls", "beatboxes", "undresses", "vomits", "whistles", "rollerblades",
"explodes"];
var strangeVerbsObj=["stab", "fight", "smack", "bury", "kick", "exorcise",
"kidnap", "high five", "sniff", "smuggle", "tickle", "cuddle", "nibble"];
var strangeVerbsGerund=["dancing", "dying", "melting", "yodeling", "sneezing",
"doing yoga","crawling", "sleeping", "undressing", "vomiting", "whistling",
"rollerblading", "exploding"];
var strangeVerbsObjGerund=["stabbing", "fighting", "smacking", "burying",
"kicking", "exorcising", "kidnapping", "high fiving", "sniffing", "smuggling",
"tickling", "cuddling", "nibbling"];
var locationWords=["behind", "in front of", "next to", "inside of", "below",
"on top of", "above", "under", "among", "beside", "over", "far away from",
"underneath"];
var comparison=["darker", "sadder", "bigger", "smaller", "harder", "softer",
"better", "worse", "faster", "slower", "stronger", "weaker", "happier", 
"drunker", "older", "younger", "smarter", "dumber", "hotter", "colder"];
var personQuote=["Albert Einstein", "Mahatma Gandhi", "Oprah Winfrey",
"George Washington", "Nelson Mandela", "Jesus Christ", "Benjamin Franklin",
"Plato", "Mother Teresa", "My mom", "Beyonce", "Martin Luther King Jr.",
"Santa Claus"]

//variable for the quote templates
var whichQuote;

/*nCh=nineteen choices, tCh=twelve choices
There are multiple variables to prevent parts of speech with same amount of
choices don't get constantly paired with each other */

var nCh1;
var nCh2;
var nCh3;
var nCh4;
var tCh1;
var tCh2;
var tCh3;
var tCh4;

//Variables related to drawing the speech bubble
var txt;
var txtH;
var bubbleHeight;
var singleLineHeight;
var bubbleX = 0;
var bubbleY = 0;
var drawBubble = false;
var bubbleID = -1;
var inspiroMeter=0;

function updateBubble(){
//randomizes which number in the array will be chosen for the parts of speech
    nCh1=int(random(20));
    nCh2=int(random(20));
    nCh3=int(random(20));
    nCh4=int(random(20));
    tCh1=int(random(13));
    tCh2=int(random(13));
    tCh3=int(random(13));
    tCh4=int(random(13));
//randomzies which quote template will be chosen
    whichQuote=int(random(14));
    inspiroMeter=inspiroMeter+20;

}

//Chooses which quote template will be chosen based on the random number
//between 0 and 13

function printQuote( num )
{

    switch(num)
  {
      case 0:
      worthTwo();
      break;
    case 1:
      tryToBe();
      break;
    case 2:
      whenYouHave();
      break;
    case 3:
      judgeEach();
      break;
    case 4:
      ifYouMiss();
      break;
    case 5:
      theBest();
      break;
    case 6:
      duringOurMoments();
      break;
    case 7:
      letUs();
      break;
    case 8:
      palesInComparison();
      break;
    case 9:
      haveSeen();
      break;
    case 10:
      inSeason();
      break;
    case 11:
      combination();
      break;
    case 12:
      onlyICan();
      break;
    case 13:
      jokeQuote();
     break;
  }
}

//Below are all the quote template functions
//bubbleHeight changes the size of bubble when there are different amounts of text

function tryToBe(){
    text("Try to be a "+inspireNouns[nCh1]+" in someone's "
    +strangeNouns[nCh2], txt, singleLineHeight);
    bubbleHeight=75;
}

function worthTwo(){
    text("One "+inspireNouns[nCh1]+" is worth two "+
    strangeNounsPlural[nCh2], txt, singleLineHeight);
    bubbleHeight=75;
}

function whenYouHave(){
    text("When you have a "+strangeNouns[nCh1]+", you've got to ", txt, txtH);
    text(inspireVerbsObj[tCh1]+" it and never "+strangeVerbsObj[tCh2]+
    " it", txt, txtH+25);
    bubbleHeight=130;
}

function judgeEach(){
    text("Don't judge each day by the "+inspireNounsPlural[nCh1],
    txt, txtH);
    text(" you "+inspireVerbsObj[tCh1]+", but by the "+strangeNounsPlural[nCh1]
    +" you "+strangeVerbsObj[tCh1], txt, txtH+25);
    bubbleHeight=130;
}

function ifYouMiss(){
    text("Shoot for the "+inspireNouns[nCh1]+", and if you miss", txt, txtH);
    text(" you will still be "+locationWords[tCh1]+" the "
    +strangeNounsPlural[nCh2], txt, txtH+25);
    bubbleHeight=130;
}

function theBest(){
    text("The best preparation for tomorrow is", txt, txtH);
    text(strangeVerbsObjGerund[tCh1]+" your "+
    strangeNouns[nCh1]+" today", txt, txtH+25);
    bubbleHeight=130;
}

function duringOurMoments(){
    text("It is during our "+comparison[nCh1]+" moments that we must", txt, txtH);
    text("focus to "+strangeVerbsObj[tCh1]+" the "+
    strangeNounsPlural[nCh2], txt, txtH+25);
    bubbleHeight=130;
}

function letUs(){
    text("Let us sacrifice our "+inspireNounsPlural[nCh1]
    +" so that", txt, txtH);
    text("our children can "+strangeVerbsObj[tCh1]+" a "+
    comparison[nCh2]+" "+strangeNouns[nCh3], txt, txtH+25);
    bubbleHeight=130;
}

function palesInComparison(){
    text("What "+inspireVerbs[tCh1]+" behind you and what "+
    inspireVerbs[tCh2]+" in front of you,", txt, txtH);
    text("pales in comparison to what "+strangeVerbs[tCh3]+" "+
    locationWords[tCh4]+" you", txt, txtH+25)
    bubbleHeight=130;
}

function haveSeen(){
    text("If I have seen further than others, it is", txt, txtH);
    text("by "+strangeVerbsGerund[tCh1]+" "+locationWords[tCh2]+" "
    +strangeNounsPlural[nCh1], txt, txtH+25)
    bubbleHeight=130;
}

function inSeason(){
    text(abstractNouns[nCh1]+" is a fruit in season at all times,", txt, txtH);
    text("and within reach of every "+strangeNouns[nCh2], txt, txtH+25);
    bubbleHeight=130;

}
function combination(){
    text(abstractNouns[nCh1]+" and "+strangeNounsPlural[nCh2]+
    " are a powerful combination", txt, singleLineHeight);
    bubbleHeight=75;
}


function onlyICan(){
    text("Only you can "+strangeVerbsObj[tCh1]+" your "+strangeNouns[nCh1]+".",
    txt, txtH);
    text("No one else can do it for you.", txt, txtH+25);
    bubbleHeight=130;
}

function jokeQuote(){
    text("This project definitely deserves an A", txt, txtH);
    text("-- "+personQuote[tCh1], txt+15, txtH+25);
    bubbleHeight=130;
}

For our final project, we made an Inspirational Quote Maze. The player moves a small square around in a randomly generated maze using the WASD keys. The dots in the maze tell the player inspirational quotes when they collide. For every quote the character receives, they gain a couple points in their “InspiroMeter.” Once they hear enough quotes, the game is over and they are congratulated for being inspired.
            Thomas mainly worked in the wall, player, and patterns files. He made the player movements and randomly generated the maze and the dots found within. He made it so the player can’t receive a different quote from the same dot twice in a row. He also created patterns to make the blocks look more exciting. 
            Anna mainly worked in the main and quotes files. She decided on the quote templates, made arrays filled with parts of speech, and randomized both of them for unique quotes. She made the speech bubble that appears when a character is talking. She also made the “InspiroMeter” and made the game end after a certain number of quotes. 
            Overall, we think that our project turned out well and we are proud of our efforts!

rfarn and ziningy1- final project

Audio embedded, please turn up volume. Vimeo recording also included at bottom.

In our final project, we made a music video and explored the relationship between geometric motion and rhythm. We divided the video into four sections of movements, interacting with the rhythm and mood of the music.

Motion section 1: Morphing blob

Motion section 2: Droplets

Motion section 3: Interacting Balls

 

Motion section 4: Splitting /Pulsing Balls

sketch

//stores music
var song;

//intro blob variables
var dx1;
var dy1;
var v0x;
var v0y;
var v1x;
var v1y;
var v2x;
var v2y;
var v3x;
var v3y;
var v4x;
var v4y;
var v5x;
var v5y;
var vcolor = 100;
var vopac = 255; 

//circle droplet variables
var diam1 = 30;
var diam2 = 30;
var diam3 = 30;
var diam4 = 30;
var opac = 200;
var drate = 6;

//interacting balls variables
var IBdiam = 30;
var IBxpos1 = 20;
var IBypos1 = 20;
var IBxpos2 = 20;
var IBypos2 = 20;
var IBxpos3 = 20;
var IBypos3 = 20;
var IBxpos4 = 20;
var IBypos4 = 20;
var IBxpos5 = 20;
var IBypos5 = 20;
var triangleOpac = 255;

//red bars variables
var bwidth1 =  15; 
var bheight = 15;
var bwidth2 = 15;
var barOpac = 255;
var bspeed = 4;
var rectx1 = 200;
var rectx2 = 230;

//splitting balls variables
var SBypos = -15;
var SBxpos1 = 300;
var SBxpos2 = 300;
var ball3y = 200;
var ball4y = 200; 


function preload() {
    song = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/music.mp3");
    song.setVolume(0.5);
}

function setup() {
    createCanvas(600, 400);
    frameRate(10);
    song.play();

    //set values to intro blob vertexes
    v0x = width/2 - 70;
    v0y = height/2;
    v1x = width/2;
    v1y = height/2 - 70;
    v2x = width/2 + 70 ;
    v2y = height/2 ;
    v3x = width/2;
    v3y = height/2 + 70;
    v4x = width/2 - 70;
    v4y = height/2;
    v5x = width/2;
    v5y = height/2 - 70;
    v6x = width/2 + 70;
    v6y = height/2;
}

function draw() {
        angleMode(DEGREES);
        background(150);
        noStroke();

        fill(vcolor);
        vcolor += 2;
        drawintroDrop(); //larger intro blob
        fill(130, 130, 130, vopac);
        push();
        scale(0.4);
        translate(2 * width/3 + 20, 2 * height/3);
        drawintroDrop(); //smaller intro blob
        pop();
        vopac -= 10;
    
        drawDroplets();
        drawInteractballs();
        pulsingBalls();
}

function interactingBalls(op, xpos, ypos) { //make interacting ball
    fill(132, 190, 160, op);
    ellipse(xpos, ypos, 30, 30);     
}

function makeDrop(r, g, b, x, y, diam) { //make droplet
    fill(r,g,b,opac);
    ellipse(x, y, diam, diam);
}

function drawintroDrop(){ //intro blob 
    angleMode(DEGREES);
    beginShape();
    curveVertex(v0x, v0y);
    v0x -= 2;
    v0y += 4;
    curveVertex(v1x, v1y);
    v1x -= 2;
    v1y += 6;
    curveVertex(v2x, v2y);
    v2x -= 8;
    v2y -= 4;
    curveVertex(v3x,v3y);
    v3x += 2;
    v3y -= 4;
    curveVertex(v4x,v4y);
    v4x += 8;
    v4y += 4;
    curveVertex(v5x, v5y);
    v5x -= 2;
    v5y += 6;
    curveVertex(v6x, v6y);
    v6x -= 2; 
    v6y += 4;
    endShape();
} 

function drawDroplets(){ //circle droplets
    if(frameCount > 52){ //first droplet
        makeDrop(108,163,140,width/4, height/4, diam1);
        diam1 += drate;
        opac -= 3;
    }

    if(frameCount > 62){ //second droplet
        makeDrop(108,123,140,width/2, height/2 + 60, diam2);
        diam2 += drate;
    }

    if(frameCount > 73){ //third droplet
        makeDrop(178,160,140,width - 100, height - 100, diam3);
        diam3 += drate;
    }

    if(frameCount > 88){ //fourth droplet
        makeDrop(200,163,140,width - 140, height - 270, diam4);
        diam4 += drate;
    }

    if(frameCount > 120 & frameCount % 3 == 0 ){ //flashing background
        fill(252, 252, 240);
        rect(0, 0, width, height);
    }
}

function drawInteractballs(){ //interacting balls
    if(frameCount > 120 & frameCount < 172 ){ //red triangle
        fill(210, 65, 65, triangleOpac);
        triangle(30, 45, 30, 135, 165,135);
    }

    //balls movement
    if(frameCount > 120){ //ball one
        interactingBalls(250, IBxpos1, IBypos1);
        IBxpos1 += 6;
        IBypos1 += 4;
        if(IBxpos1 > 165 + IBdiam/3){
            IBxpos1 -= 3;
            IBypos1 += 10;
        } 
        if(IBypos1 > 350 - IBdiam/2 || frameCount > 161){
            IBxpos1 -= 1;
            IBypos1 -= 20;
        }
        if(frameCount > 185){
            IBypos1 += 12;
        }
        if(frameCount > 211){
            IBypos1 -= 12;
        }
        if(frameCount > 237){
            IBypos1 += 18;
        }
    }

    if(frameCount>126.5){ //ball two
        interactingBalls(180, IBxpos2, IBypos2);
        IBxpos2 += 6;
        IBypos2 += 4;
        if(IBxpos2 > 165 + IBdiam/3){
            IBxpos2 -= 3;
            IBypos2 += 10;
        }
        if(IBypos2 > 350 - IBdiam/2 || frameCount > 167.5){
            IBxpos2 -= 1;
            IBypos2 -= 20;        
        }
        if(frameCount > 191.5){
            IBypos2 += 12;
        }
        if(frameCount > 217.5){
            IBypos2 -= 12;
        }
        if(frameCount > 244.5){
            IBypos2 += 18;
        }
    }

    if(frameCount > 133){ //ball three
        interactingBalls(130, IBxpos3, IBypos3);
        IBxpos3 += 6;
        IBypos3 += 4;
        if(IBxpos3 > 165 + IBdiam/3){
            IBxpos3 -= 3;
            IBypos3 += 10;
            triangleOpac -= 17; //triangle opacity decreases when third ball falls
        }
        if(IBypos3 > 350 - IBdiam/2 || frameCount > 174){
            IBxpos3 -= 1;
            IBypos3 -= 20;
        }
        if(frameCount > 198){
            IBypos3 += 12;
        }
        if(frameCount > 224){
            IBypos3 -= 12;
        }
        if(frameCount > 251){
            IBypos3 += 18;
        }
    }

    if(frameCount>139.5){ //ball four
        interactingBalls(80, IBxpos4, IBypos4);
        IBxpos4 += 6;
        IBypos4 += 4;
        if(IBxpos4 > 165 + IBdiam/3){
            IBxpos4 -= 3;
            IBypos4 += 10;
        }
        if(IBypos4 > 350 - IBdiam/2 || frameCount > 180.5){
            IBxpos4 -= 1;
            IBypos4 -= 20;
        }
        if(frameCount > 204.5){
            IBypos4 += 12;
        }
        if(frameCount > 230.5){
            IBypos4 -= 12;
        }
        if(frameCount > 257.5){
            IBypos4 += 18;
        }
    }

    if(frameCount>146.5){ //ball five
        interactingBalls(40, IBxpos5, IBypos5);
        IBxpos5 += 6;
        IBypos5 += 4;
        if(IBxpos5 > 165 + IBdiam/3){
            IBxpos5 -= 3;
            IBypos5 += 10;
        }
        if(IBypos5 > 350 - IBdiam/2 || frameCount > 186.5){
            IBxpos5 -= 1;
            IBypos5 -= 20;
        }
        if(frameCount > 211){
            IBypos5 += 12;
        }
        if(frameCount > 237){
            IBypos5 -= 12;
            barOpac -= 7; //red bars opacity decreases on fifth balls second to last bounce
        }
        if(frameCount > 264){
            IBypos5 += 18;
        }
    }

    //red bars
    if(frameCount > 159){ //bottom bar
        fill(210, 65, 65, barOpac);
        rect(rectx1,345,bwidth1,bheight);
        bwidth1+= bspeed;
    }

    if(frameCount > 175){ //top bar
        fill(210, 65, 65, barOpac);
        rect(rectx2,155,bwidth2,bheight);
        bwidth2 += bspeed;
    }

    if(bwidth1 > 350  || frameCount > 212){ //bars moving right
        rectx1 += 7;
        rectx2 += 2;
    }
}

function pulsingBalls(){ //splitting and pulsing balls
    //constraining variables
    var SBy1 = constrain(SBypos, -IBdiam/2, height/2);
    var SBx1 = constrain(SBxpos1, width/3 - 25, width);
    var SBx2 = constrain(SBxpos2, 0, width * (2/3) + 25);
    
    if(frameCount > 287){ //first circle moving
        fill(132, 190, 160);
        SBypos += 10;
        ellipse(SBx1, SBy1, IBdiam, IBdiam);
        ellipse(SBx2, SBy1, IBdiam, IBdiam);
        if(SBy1 > 160 & SBy1 < 200){ //diam increases
            IBdiam += 5;
        }
        if(SBy1 == 200){ //split to two circles
            SBxpos1 -= 5;
            SBxpos2 += 5;
            if(frameCount>330){ //split to six circles
                var SBy2 = constrain(ball3y, height/4, height/2);
                var SBy3 = constrain(ball4y, height/2, height * (3/4));
                ellipse(SBx1, SBy2, IBdiam, IBdiam); 
                ellipse(SBx1, SBy3, IBdiam, IBdiam);
                ellipse(SBx2, SBy2, IBdiam, IBdiam); 
                ellipse(SBx2, SBy3, IBdiam, IBdiam);
                ball3y -= 10; 
                ball4y += 10;
                if(SBy2 > 130 & SBy2 < 170){ //diam increases
                    IBdiam += 3; 
                }
            }
        }
    }

    //pulsing balls 
    if(frameCount > 350 & frameCount % 2 == 0){
        IBdiam += 16;
    }

    if(frameCount > 360 & frameCount % 3 == 0){
        IBdiam -= 20;
    }
}