Final Project: Video Effects with a Pseudo Half Tone

I wanted to do something having to do with video effects and I eventually settled on this version. Ok for starters, I came across several challenges–> the first of which was, how am I going to embed this into my website? With some aggressive internet scouting, I dove deeper into javascript and jQuery learned about new functions like getContext() and offsetWidth()–> These were straight JS functions that I learned I could integrate nicely with html and css. I also edited in codepen so I could play around with html, css, and js at the same time.

Also with some experimenting I used const instead of var because I discovered that when I used var, the blocks became much too cumbersome.

Halftone large, no restrictions
halftone, with restrictions

This in addition to some other changes, I was able to create a much clearer video image.

The whole project can be found here on codePen.

Jason Zhu & Miranda Luong – Final Project

****Note: Project does not properly run on Safari. Run on Chrome.****
If you’d like, we’ve uploaded this zip file containing all assets to our project. Open this program like any other p5js sound sketch using a local server. To do so make sure you follow the instructions noted in https://courses.ideate.cmu.edu/15-104/f2018/lab-week-11/ under Task B: Triggering sound file playback.

sketch

/*
Issho, an audio visualizer by Miranda Luong and Jason Zhu.

Our final project is an audio visualizer named Ishho, derived from the Sino-Japanese
word for "impression". To say that Ishho is just an audio visualizer would be an 
understatement. Our high level goal was to give music its own unique visual identity
––similar to some of the work of Neil Harbisson who has created color portraits of various 
songs. Our secondary goal was to create this unique visual identity in real time.
*/

// Global audio variables.
var PREFIX = "https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/moi-je-bouge.mp3"
var song;
var amplitude;
var fft;
var peakDetect;

// Global line variables.
var nLines = 88;
var linesArray = [];
var nforces = 4;
var nParticles = 88;
var forcesArray = [];
var fillScreen = true;
var strokeW = 1;

// Preload song.
function preload(){
  song = loadSound(PREFIX);
}

function setup() {
  createCanvas(500, 500);
  frameRate(60);

  // Audio setup.
  amplitude = new p5.Amplitude();
  amplitude.setInput(song);
  fft = new p5.FFT();
  fft.setInput(song);
  peakDetect = new p5.PeakDetect(20,20000,.06,.00694444444);
  song.play();

  // Setup line and force particles.
  initialize();
}

function draw() {
  if (song.isPlaying()){

    // Start display with noFill(). Toggle between white and black backgrounds by
    // pressing 'spacebar' key and changing var fillScreen's boolean value.
    noFill();
    if (fillScreen){
      background(0);
    } else {
      background(255);
    }

    // Update audio analyzer.
    fft.analyze();
    peakDetect.update(fft);

    for (var i = 0; i < nforces; i++) {
      forcesArray[i].move();
    }

    // Standard radius
    var radius = 75 * cos(frameCount / 80);

    //If beat is detected, enlargen radius based on level of amplitude.
    if (peakDetect.isDetected){
      var radius = map(amplitude.getLevel(),.06, .3, 10, 150) * cos(frameCount/80);
    }

    // Setup a range of two colors for the gradient coloring of lines 
    // and have the gradient change as the song and animation progress.
    var highRed = map(song.currentTime()* 3.5, 0, song.duration() * 3, 255, 0);
    var highGreen = map(song.currentTime()*3.5, 0, song.duration() * 3, 0, 255);

    // Setup rate of gradient change between colors depending on amplitude 
    // of the song at that current time.
    var low = 30;
    var high = map(amplitude.getLevel(), 0, .125, 0, 255);
    
    for (var i = 0; i < linesArray.length; i++) {
      // Create interaction for every line with every force particle.
      linesArray[i].interact(radius, forcesArray[0].position.x, forcesArray[0].position.y);
      linesArray[i].interact(radius, forcesArray[1].position.x, forcesArray[1].position.y);
      linesArray[i].interact(-radius, forcesArray[2].position.x, forcesArray[2].position.y);
      linesArray[i].interact(-radius, forcesArray[3].position.x, forcesArray[3].position.y);
    
      // Color lines using a gradient.
      var col = lerp(low, high, i / linesArray.length);
      stroke(highRed, highGreen, col);

      // Change strokeweight of lines depending on amplitude of song at the given time.
      if (strokeW >= 5){
        strokeW = 1;
      }
      strokeWeight(strokeW);

      linesArray[i].draw();
    }
  }
}

function initialize() {
  // Create and store Lines into linesArray.
  for (var i = 0; i < nLines; i++) {
    linesArray[i] = new Line(42 + 4.8* i);
    linesArray[i].addParticles();
  }
  // Create and store force particles in forcesArray.
  for (var i = 0; i < nforces; i++) {
    if (i== 0){
    forcesArray[i] = new Particle(30+ (1) * 470 / 3, 42 + (1) * 423 / 3);
    }
    if (i == 1){
      forcesArray[i] = new Particle(30+ (2) * 470 / 3, 42 + (2) * 423 / 3);
    }
    if (i == 2){
      forcesArray[i] = new Particle(30+ (1) * 470 / 3, 42 + (2) * 423 / 3);
    }
    if (i == 3){
      forcesArray[i] = new Particle(30+ (2) * 470 / 3, 42 + (1) * 423 / 3);
    }

    // Start force particles with random velocities.
    var angle = random(0, TWO_PI);
    forcesArray[i].velocity.set(cos(angle), sin(angle));
  }
}

// Click to play and pause animation and song.
function mousePressed() {
  if (song.isPlaying()){
    song.pause();
  } else {
    song.play();
  }
}

function keyPressed() {
  // Toggle between black or white backgrounds by pressing 'spacebar'.
  if (key === ' ') {
    fillScreen = !fillScreen;
  }
  // Press 's' to increase strokeWeight or later reset to 1
  if (key === 's') {
    strokeW += 1;
  }
}

// Line class.
var Line = function(y){
  this.y = y;
  this.particlesArray = [];
}

// Add particles to lines particlesArray.
Line.prototype.addParticles = function(){
  for (var i = 0; i < nParticles; i++){
    this.particlesArray.push(new Particle(30 + 5 * i, this.y));
  }
}

// Connect all particles in line's particleArray to draw line.
Line.prototype.draw = function(){    
  beginShape();
    for (var i = 0; i < this.particlesArray.length; i++) {
      curveVertex(this.particlesArray[i].position.x, this.particlesArray[i].position.y);
    }
  endShape();
}


// Interact line with force particles by having all of 
// line's particles individually interact with force particles.
Line.prototype.interact = function(radius, xpos, ypos) { 
  for (var i = 0; i < this.particlesArray.length; i++) {
    this.particlesArray[i].interact(radius, xpos, ypos);
  }

  // Change size of line when necessary to make for smooth texture.
  for (var i = 0; i < this.particlesArray.length-1; i++) {
    var d = dist(this.particlesArray[i].position.x, this.particlesArray[i].position.y, 
                 this.particlesArray[i+1].position.x, this.particlesArray[i + 1].position.y);
    
    // Add a new Particle to particleArray when two neighbor particles are too far apart.
    if (d > 5) {
      var x = ((this.particlesArray[i].position.x + this.particlesArray[i + 1].position.x) / 2);
      var y = ((this.particlesArray[i].position.y + this.particlesArray[i + 1].position.y) / 2);
      this.particlesArray.splice(i + 1, 0, new Particle(x, y));
    }

    // Remove a particle when 2 neighbor particles are too close.
    if (d < 1) {
      this.particlesArray.splice(i, 1);
    }
  }     
}

// Particle class.
var Particle = function(x, y){
  this.position = createVector(x, y);
  this.velocity= createVector(0, 0);
  this.acceleration = createVector(0, 0);
}

// Updates force particles' positions.
Particle.prototype.move = function(){
  // Change direction of force particles sometimes.
  if (random(1) > .97){
    var angle = random(-PI, PI);
    this.acceleration.set(cos(angle), sin(angle));
    var mod = this.acceleration.angleBetween(this.velocity);
    mod = map(mod, 0, PI, 0.1, 0.001);
    this.acceleration.mult(mod); 
  }

  // Change pace of force particle's position change
  this.velocity.add(this.acceleration);

  // Stop if current amplitude reaches or surpasses 0.675.
  // Force particle to increase impact of interaction with lines.
  if (amplitude.getLevel() > .675){
      this.velocity.set(0, 0);
  }

  // Move force particle
  this.position.add(this.velocity);

  // Check edges.
  this.position.x = (this.position.x + width)%width;
  this.position.y = (this.position.y + height)%height;
}

// Force particle to line particle interaction.
Particle.prototype.interact = function(radius, xpos, ypos){
  var dir = radius/abs(radius);
  var radius = abs(radius);

  var r = dist(this.position.x, this.position.y, xpos, ypos);
  var angle = atan2(this.position.y - ypos, this.position.x - xpos);

  // If line particle is within radius of force particle,
  // change velocity to change position of line particle.
  if (r <= radius) {
    // If cuerrent amplitude is greater than .05, generate wider,
    // radial movement from particles to highlight song's beats.
    if (amplitude.getLevel() > .05){
      var radius = 2 * dir * (radius - r) / radius;
    }
    else{ 
      var radius = .3 * dir * (radius - r) / radius;
    }
    this.velocity.set(radius * cos(angle), radius * sin(angle));
  } else {
    this.velocity.set(0, 0);
  }
  this.position.add(this.velocity);
}

 

Preface
Our final project is an audio visualizer which we have named Ishho, derived from the Sino-Japanese word for “impression”. Our original proposal was to have ripples radiate from a central node that would affect geometry in order to create complex forms. While this still holds true to some extent, feedback in our project proposal in addition to further research, particularly the work of Japanese design studio, teamLab, led us to reconsider.

To say that Ishho is just an audio visualizer would be an understatement. Our high-level goal was to give music its own unique visual identity-similar to some of the work of Neil Harbisson who has created color portraits of various songs. Our secondary goal was to create this unique visual identity in real time.

Project Description
We accomplished our high-level and secondary goals by breaking down the audio into its duration, peaks, amplitudes. We used these variables to affect various aspects of our base canvas. The base canvas starts with straight lines that run across the page. These lines are colored with a gradient that changes according to the relation of the song’s current time to its overall duration. The rate of which the gradient changes from its bottom color to its top is governed by the amplitude of the song at that given time. So impactful beats are displayed onto these lines. In addition to this visualization, we used music to imprint the terrain that our base lines created. From the start, hidden force particles lightly push and interact with the lines, creating minimal impressions on our canvas, but when a beat is detected, the force particles’ effects are magnified. This effect is calculated by the amplitude of that beat and has the potential to create large valleys, dips and ridges in our canvas terrain. 

Division of Work
As per the guidelines and to make the project more feasible, we decided to divide the work into what we felt was an equitable 50-50 split. Miranda did the research on particle systems and from there coded the basis  for our audio visualizer. She setup the Line and Particle classes, defined the individual force particles and created their respective arrays. Update and interaction functions were also reasoned using her math. Jason focused on integrating music into the code and adding interactive elements such as toggling backgrounds and changing stroke weights. With his research on the sound library, he considered ways to best visualize the beats in our song with the use of line movement and negative space.

test

test

// bouncing ball example

var x, y, dx, dy;
var r = 30; // radius
var g = 0.1; // gravity

var mySnd;

function preload() {
    mySnd = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/139875__y89312__44-1.wav");
    mySnd.setVolume(0.5);
}


function setup() {
    createCanvas(400, 400);
    x = 200;
    y = 40;
    dx = 0;
    dy = 0;
}

function draw() {
    background(200, 220, 250);
    fill(0, 250, 0);
    ellipse(x, y, r, r);
    x = x + dx;
    y = y + dy;
    var travel_since_bounce = y - (height - r / 2);
    if (travel_since_bounce > 0) {
        // after bounce we should have gone in the other direction
        // so undo travel and travel in the opposite direction,
        // therefore we need to subtract travel * 2 from y
        y = y - travel_since_bounce * 2;
        dy = -dy; // change direction
        mySnd.play();
    }
    dy = dy + g; // gravity
}

Lan Wei-Final Project-MUSICAL UNIVERSE

sketch

//Lan Wei
//lanw@andrew.cmu.edu
//Section // D
//Final Project-Musical Universe

var snd = []; //this array will hold the sounds
var amplitude = [];
var ampTotal; //Total amplitude to change background color
var mouseXArray = []; //the array of X values
var mouseYArray = []; //the array of y values
var balls = []; //the array of ball objects
var np = 26; //the number of background lines
var pArray = []; //the array of particles

//preload the sounds
function preload() {
    var PREFIX = "https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/";
    for (var i = 1; i < 10; i++){
        var sound = loadSound(PREFIX + "sound" + i + ".wav"); //load sounds
        sound.setVolume(0.5);
        snd.push(sound); //push the sounds in snd. var sound will never be used again
    }
}

//make ball objects
function makeBalls(bx, by, br){
    var ball = {x: bx,
                y: by,
                r: br, //radius of the ball
                update: updateBall, //update the size of the balls
                sound: whichSound, //which amplitude is the ball related to
                draw: drawBall,
                play: playSound};
    return ball; //return the new object
}

function drawBall(){
    stroke(255);
    //ellipse(this.x, this.y, this.r, this.r);
    var total = 20; //control the density of the points on the balls
    for (var i = 0; i < total; i++){
        var longtitude = map(i, 0, total, -PI, PI);
        for (var j = 0; j < total; j++){
            var latitude = map(j, 0, total, -HALF_PI, HALF_PI);
            //fold the longtitude-latitude panel into a sphere
            var ptX = this.r * sin(longtitude) * cos(latitude);
            var ptY = this.r * sin(longtitude) * sin(latitude);
            var ptZ = this.r * cos(longtitude);
            push();
            stroke(255);
            translate(ptX, ptY, ptZ);
            sphere(0.1);
            pop();
        }
    }
}

function whichSound(){
    if (zone(this.x, this.y) == 1){
        return snd[0];
    }
    if (zone(this.x, this.y) == 2){
        return snd[1];
    }
    if (zone(this.x, this.y) == 3){
        return snd[2];
    }
    if (zone(this.x, this.y) == 4){
        return snd[3];
    }
    if (zone(this.x, this.y) == 5){
        return snd[4];
    }
    if (zone(this.x, this.y) == 6){
        return snd[5];
    }
    if (zone(this.x, this.y) == 7){
        return snd[6];
    }
    if (zone(this.x, this.y) == 8){
        return snd[7];
    }
    if (zone(this.x, this.y) == 9){
        return snd[8];
    }
}

function playSound(){
    var soundLocal = this.sound();
    soundLocal.play();
}

function updateBall(){
    var amp = amplitude[zone(this.x, this.y) - 1];
    var level = amp.getLevel(); //get the level
    this.r = 30 + 300 * level; //the size of balls
}

//particles to make background lines
function makeParticle(px, py, pdx, pdy){
    p = {x: px,
         y: py,
         dx: pdx,
         dy: pdy,
         update: pUpdate,
         draw: pDraw}
    return p;
}

function pUpdate(){
    this.x += this.dx;
    this.y += this.dy;

    //limit the lines in a certain area of 500 * 500 using 'bouncing'
    if (this.x < -250){ //left boundary
        this.x = -this.x - 250;
        this.dx = -this.dx - 250;
    }
    else if (this.x > 250){ //right boundary
        this.x = 300 - this.x;
        this.dx = 300 - this.dx;
    }
    if (this.y < -250){ //downward boundary
        this.y = -this.y - 250;
        this.dy = -this.dy - 250;
    }
    else if (this.y > 250){ //upward boundary
        this.y = 300 - this.y;
        this.dy = 300 - this.dy;
    }
}

function pDraw(){
    ellipse(this.x, this.y, 5, 5);
}
/////////////////////////////////////////////////////////////////////////////////////
function setup() {
    createCanvas(450, 450, WEBGL); // 3D mode. (0, 0)locates in the center of the canvas
    background(0);
    stroke(255);
    perspective(); //perspective view

    for (var i = 0; i < 9; i++){
        amplitude[i] = new p5.Amplitude();
        amplitude[i].setInput(snd[i]); //get independent amplitude
    }
    ampTotal = new p5.Amplitude(); //total amplitude

    for (var i = 0; i < np; i++){
        //the boundary of particles is a little bigger than the canvas
        var p = makeParticle(random(-300, 300), random(-300, 300), random(-2, 2), random(-2, 2));
        pArray.push(p);
    }
}

function draw() {
    var levelTotal = ampTotal.getLevel();
    var col = map(levelTotal, 0, 1, 0, 100);//background color
    background(col, 0, 2 * col);
    //draw background lines
    for (var i = 0; i < np; i++){
        pArray[i].update();
        pArray[i].draw();
        //lines between particles
        for (var j = 0; j < np/2; j++){
            stroke(random(0, 150));
            strokeWeight(0.2);
            line(pArray[j].x, pArray[j].y, pArray[j + np/2].x, pArray[j + np/2].y);
        }
    }
    //the canvas is divided by a 3*3 grid
    strokeWeight(1);
    stroke(random(20, 70));
    line(-75, -225, -75, 225);
    line(75, -225, 75, 225);
    line(-225, -75, 225, -75);
    line(-225, 75, 225, 75);

    if (mouseXArray.length != 0){ //after the 1st mouse press
        stroke(255);
        fill(255);
        // draw all the balls
        for (i = 0; i < balls.length; i ++){
            balls[i].update(); //update the radius of the balls
            push();
            translate(balls[i].x, balls[i].y, 0);
            //rotate with randomness
            rotateX(frameCount * 0.05 + i);
            rotateY(frameCount * 0.05 + i * 5);
            rotateZ(frameCount * 0.05 + i * 5);
            balls[i].draw(); //draw the balls
            pop();
        }
    }
}

//To identify which zone is the ball in
//translate the coordinate to normal mode
function zone(x, y){
    if ((y > -225 )& (y < height/3 - 225)){
        if ((x > -225) && (x < width/3 - 225)){ //position 1
            return 1;
        }
        if ((x > width/3 - 225) & (x < 2 * width/3 - 225)){ //position 2
            return 2;
        }
        if ((x > 2 * width/3 - 225) & (x < width - 225)){ //position 3
            return 3;
        }
    }

    if ((y > height/3 - 225) & (y < 2 * height/3 - 225)){
        if ((x > -225) && (x < width/3 - 225)){ //position 4
            return 4;
        }
        if ((x > width/3 - 225) & (x < 2 * width/3 - 225)){ //position 5
            return 5;
        }
        if ((x > 2 * width/3 - 225) & (x < width - 225)){ //position 6
            return 6;
        }
    }

    if ((y > 2 * height/3 - 225) & (y < height - 225)){
        if ((x > -225) && (x < width/3 - 225)){ //position 7
            return 7;
        }
        if ((x > width/3 - 225) & (x < 2 * width/3 - 225)){ //position 8
            return 8;
        }
        if ((x > 2 * width/3 - 225) & (x < width - 225)){ //position 9
            return 9;
        }
    }
}

//when mouse is clicked, a sound will be played and a ball will be drawn
function mouseClicked(){
    var clickOn; //to check whether click on an existing ball
    var newBalls = [];
    var newMouseXArray = [];
    var newMouseYArray = [];

    if (mouseXArray.length == 0){ //when there is no existing balls
        clickOn = 0;
        newBalls.push(balls[0]);
        newMouseXArray.push(mouseXArray[0]);
        newMouseYArray.push(mouseYArray[0]);

    }

    // a ball will be removed when clicked again
    else{ //after the 1st click
        for (i = 0; i < balls.length; i++){
            var distance = dist(mouseX - 225, mouseY - 225, balls[i].x, balls[i].y);
            //is clicked
            if (distance <= 20){ //minimum distance
                var soundBall = balls[i].sound();
                soundBall.setVolume(0); //stop the sound of the ball that's clicked
                // balls.splice(i, 1); //remove the ball
                // mouseXArray.splice(i, 1);
                // mouseYArray.splice(i, 1);
                clickOn = 1;
            }
            //is not clicked
            else{
                clickOn = 0;
                newBalls.push(balls[i]);
                newMouseXArray.push(mouseXArray[i]);
                newMouseYArray.push(mouseYArray[i]);
            }
        }
        balls = newBalls;
        mouseXArray = newMouseXArray;
        mouseYArray = newMouseYArray;
    }
    if (clickOn == 0){
        mouseXArray.push(mouseX - 225);//translate to WEBGL coordinates
        mouseYArray.push(mouseY - 225);
        // initial radius: 30
        //make ball objects
        var newBall = makeBalls(mouseX - 225, mouseY - 225, 30);
        balls.push(newBall);

    }
    //play sound using the object
    for (i = 0; i < balls.length; i++){
        var soundLocal = balls[i].sound();
        balls[i].play();
        soundLocal.loop();
    }
}

//YOU'VE GOT A MUSICAL UNIVERSE!!!

[How to play]: Click on different positions of the canvas to get different mixtures of ‘UNIVERSE MUSIC’,click the balls again to remove them as well as the sound (in the opposite order you created the balls). Play slowly! (Sometimes it doesn’t work well if played fast, maybe it’s my browser’s problem.)

My initial idea of the project is to create a simple instrument that enables users to mix several pieces of music. In the proposal stage, I have imagined many sound effects and interaction methods, but have only achieved part of them. The actual coding process is much harder than I thought, and the final result becomes more visual than auditory. But actually, I’m very happy about the project because it is really a reviewing as well as a learning process. I’m not very good at using objects and particles so I tried to include these contents in my project. And I also watched some online tutorials to create the 3D effect of the balls. The final result is very satisfying for me, especially the 3D ball effect!

Have Fun!

 

sketch

/*Carley Johnson
Section E
cbjohsno@andrew.cmu.edu
Final Project
*/

platform = [];
var x, y, y1, y2, y3;
var startScreen = 0;
var platformNumber = 50;
var platformGap = 70;
var cat;
var r = 0;

function preload() {
    var cloudPic = "https://i.imgur.com/veId7W2.jpg"
    cloudImage = loadImage(cloudPic);
    var catPic = "https://i.imgur.com/ooPSMZU.jpg"
    catImage = loadImage(catPic);
    var titlePic = "https://i.imgur.com/6ehrfne.jpg"
    titleScreen =  loadImage(titlePic);
}

function Cat() {
  this.x = 10;
  this.y = 10;
}

function Platform() {
  this.x = 10;
  this.y = 10;
  this.height = 10;
  this.width = 100;
}

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

  //cloud placements
  x = width / 2;
  y = height;
  y1 = y + 100;
  y2 = y - 75;
  y3 = y - 300;

  //title screen setup
  if (startScreen == 0) {
    image(titleScreen, -30, 0, titleScreen.width/2, titleScreen.height/2);
    noStroke();
    textFont("MV Boli");
    fill(230, 181, 224);
    textSize(48);
    textAlign(CENTER);
    text("Move Cat With Mouse,", width/2, height - 95);
    text("Click To Start!", width/2, height - 50);
  }

  angleMode(DEGREES);
  
  //setup platforms
  for (i = 0; i < platformNumber; i++) {
    platform[i] = new Platform();
    platform[i].x = random(0, 400);
    platform[i].y = 500 + i * platformGap;
  }
  
  //start the platform in the right place
  platform[0].x = mouseX;
  cat = new Cat();
  cat.x = platform[0].x + 50;
  cat.y = platform[0].y - 5;
}

function draw() {
  if (startScreen == 0) {
    }
  else if (startScreen == 1) {
        //background sky
        background(88, 179, 236);
        image(cloudImage, x, y, cloudImage.width * 1.5, cloudImage.height * 1.5);
        image(cloudImage, x - 200, y1, cloudImage.width * 1.5, cloudImage.height * 1.5);
        image(cloudImage, x - 150, y2, cloudImage.width * 1.5, cloudImage.height * 1.5);
        image(cloudImage, x - 300, y3, cloudImage.width * 1.5, cloudImage.height * 1.5);
        y = y - 1;
        y1 = y1 - 1;
        y2 = y2 - 1;
        y3 = y3 - 1;

        //Gameplay
        noStroke();
        drawPlatform();
        drawCat();

        //cloud resets
        if (y < 0) {
            y = height;
        }

        if (y1 < 0) {
            y1 = height;
        }

        if (y2 < 0) {
            y2 = height;
        }

        if (y3 < 0) {
            y3 = height;
        }
    }
    
    //Cat controls
  cat.x = mouseX;
  if (mouseX < platform[r].x || mouseX > platform[r].x + 100) {
    cat.y = cat.y + 5;

    if (cat.y > platform[r].y + 10) {
      r++;
    }
  } else {
    cat.y = platform[r].y - 5;
  }
}

function mousePressed() {
  if (startScreen == 0) {
    startScreen = 1;
  }
}

function drawPlatform() {
 
  fill(147, 100, 15);
  for (i = 0; i < platformNumber; i++) {
    rect(platform[i].x, platform[i].y, platform[i].width, platform[i].height);
    platform[i].y = 500 + i * platformGap - (frameCount / 0.7 % (500 + i * platformGap));

    //Score counter
  textSize(20);
  stroke(147, 100, 15);
  textFont("MV Boli");
  fill(147, 100, 15);
  text('SCORE:', 475, 30);
  var score = parseInt(frameCount / 42) + 1;
  text(score, 565, 30);
  }
}

function drawCat() {
  push();
  translate(cat.x, cat.y);
  image(catImage, -150, -140, catImage.width/5, catImage.height/5)
  pop();

    //Game over
  if (cat.y < 0 || cat.y > 500) {
    stroke(204, 229, 242);
    fill(204, 229, 242);
    rect(130, 200, 350, 60);
    stroke(227, 116, 214);
    textFont("MV Boli");
    fill(230, 181, 224);
    textSize(60);
    textAlign(CENTER);
    text('Game Over!', 300, 250);
    noLoop();
    noFill();
    noStroke();
  }
}

A few things to play:

Click on the start screen quickly – a bug I was unsure how to fix causes the game to start play even while the start screen is up!

Keep your mouse to the left of the screen- this is where the first platform starts!

To play again, reload the page!

Otherwise, I enjoyed working on this project! I like how it looks (I drew the title card, the cat avatar, and the cloud image myself). I wanted it to be cute and slightly doodle-y in style. I picked the colors to go with this feeling. I’m proud of this because I feel like this is the first “experience” I’ve coded. It’s short and sweet, without a ton of major mechanics, but it’s a full experience nonetheless and I’m proud of it. I feel like I was able to tick off more goals of mine they I expected, so overall I’d say it is a personal win. I ended up combining my two possible game play ideas (an upwards platformer or downwards scroller) into a downwards platformer. I picked the cat theme because I was feeling homesick for my own, so I imagined that this was my cat (Soupy) trying to get home!

Rani Randell Final Project

hi! welcome to my final project. please allow webcam access and sit in the center of your webcam for full effect. my project is a commentary on the artist John Baldessari. I have included a zip file below of my work as I am aware it may not run on WP. i will explain more and include photos of his work below:

sketch

/* Rani Randell
rrandell@andrew.cmu.edu
Section A
Final Project */

// please open in chrome and with your body centered in the middle of the webcam

var floatingText = 0
var cd = 80 //circle diameter for key pressed A
var myCamera;

function setup() {
    createCanvas(640, 480);
    myCamera = createCapture(VIDEO);
    myCamera.size(640, 480);
    myCamera.hide();  // attempt to size the camera. 
}

function draw() {

    image(myCamera, 0, 0); 
    myCamera.loadPixels(); 

    // scrolling instructions along bottom of screen
    noStroke();
    fill('yellow');
    rect(0, 400, 640, 200); //yellow bar with black scrolling writing
    textSize(40); 
    textStyle(BOLD);
    fill('black');
    textFont('Courier New');
    text('press keys a or b for a surprise', floatingText, 450);
    floatingText = floatingText + 1
    if (floatingText > 640) {
    floatingText = -750
    }

    noStroke();
    if (keyIsPressed) {

        if ((key == 'a') || (key == 'A')) { //primary colored circles
            fill('blue')
            ellipseMode(CENTER);
            ellipse(100, 100, cd, cd);
            ellipse(200, 200, cd, cd);
            ellipse(100, 200, cd, cd);
            ellipse(200, 300, cd, cd);
            ellipse(500, 100, cd, cd);
            ellipse(600, 200, cd, cd);
            ellipse(600, 300, cd, cd);
            ellipse(450, 300, cd, cd);
            ellipse(0, 0, cd, cd);
            ellipse(0, 200, cd, cd);
            ellipse(0, 300, cd, cd);
            ellipse(450, 0, cd, cd);
            ellipse(600, 0, cd, cd);
            ellipse(260, 0, cd, cd);
            ellipse(390, 0, cd, cd);
            ellipse(80, 0, cd, cd);
            ellipse(525, 260, cd, cd);
            ellipse(200, 60, cd, cd);
            ellipse(0, 150, cd, cd);

            fill('yellow');
            ellipse(0, 100, cd, cd);
            ellipse(250, 70, cd, cd);
            ellipse(200, 350, cd, cd);
            ellipse(570, 290, cd, cd);
            ellipse(480, 310, cd, cd);
            ellipse(300, 0, cd, cd);
            ellipse(640, 220, cd, cd);
            ellipse(250, 300, cd, cd);
            ellipse(0, 250, cd, cd);
            ellipse(640, 0, cd, cd);
            ellipse(210, 0, cd, cd);
            ellipse(150, 210, cd, cd);
            ellipse(470, 200, cd, cd);
            ellipse(140, 120, cd, cd);
            ellipse(600, 100, cd, cd);
            ellipse(570, 30, cd, cd);
            ellipse(120, 70, cd, cd);
            ellipse(100, 350, cd, cd);

            fill('red');
            ellipse(0, 200, cd, cd);
            ellipse(550, 330, cd, cd);
            ellipse(550, 170, cd, cd);
            ellipse(50, 170, cd, cd);
            ellipse(175, 190, cd, cd);
            ellipse(100, 300, cd, cd);
            ellipse(640, 100, cd, cd);
            ellipse(150, 0, cd, cd);
            ellipse(510, 0, cd, cd);
            ellipse(640, 290, cd, cd);
            ellipse(450, 0, cd, cd);
            ellipse(30, 77, cd, cd);
            ellipse(460, 240, cd, cd);
            ellipse(540, 50, cd, cd);
            ellipse(160, 80, cd, cd);
            ellipse(0, 350, cd, cd);
            ellipse(450, 95, cd, cd);
            ellipse(170, 280, cd, cd);

        }

        if ((key == 'b') || (key == 'B')) { //complementary colored circles
            fill('orange');
            ellipse(100, 100, cd, cd);
            ellipse(200, 200, cd, cd);
            ellipse(100, 200, cd, cd);
            ellipse(200, 300, cd, cd);
            ellipse(500, 100, cd, cd);
            ellipse(600, 200, cd, cd);
            ellipse(600, 300, cd, cd);
            ellipse(450, 300, cd, cd);
            ellipse(0, 0, cd, cd);
            ellipse(0, 200, cd, cd);
            ellipse(0, 300, cd, cd);
            ellipse(450, 0, cd, cd);
            ellipse(600, 0, cd, cd);
            ellipse(260, 0, cd, cd);
            ellipse(390, 0, cd, cd);
            ellipse(80, 0, cd, cd);
            ellipse(525, 260, cd, cd);
            ellipse(200, 60, cd, cd);
            ellipse(0, 150, cd, cd);

            fill('purple');
            ellipse(0, 100, cd, cd);
            ellipse(250, 70, cd, cd);
            ellipse(200, 350, cd, cd);
            ellipse(570, 290, cd, cd);
            ellipse(480, 310, cd, cd);
            ellipse(300, 0, cd, cd);
            ellipse(640, 220, cd, cd);
            ellipse(250, 300, cd, cd);
            ellipse(0, 250, cd, cd);
            ellipse(640, 0, cd, cd);
            ellipse(210, 0, cd, cd);
            ellipse(150, 210, cd, cd);
            ellipse(470, 200, cd, cd);
            ellipse(140, 120, cd, cd);
            ellipse(600, 100, cd, cd);
            ellipse(570, 30, cd, cd);
            ellipse(120, 70, cd, cd);
            ellipse(100, 350, cd, cd);
       

            fill('green');
            ellipse(0, 200, cd, cd);
            ellipse(550, 330, cd, cd);
            ellipse(550, 170, cd, cd);
            ellipse(50, 170, cd, cd);
            ellipse(175, 190, cd, cd);
            ellipse(100, 300, cd, cd);
            ellipse(640, 100, cd, cd);
            ellipse(150, 0, cd, cd);
            ellipse(510, 0, cd, cd);
            ellipse(640, 290, cd, cd);
            ellipse(450, 0, cd, cd);
            ellipse(30, 77, cd, cd);
            ellipse(460, 240, cd, cd);
            ellipse(540, 50, cd, cd);
            ellipse(160, 80, cd, cd);
            ellipse(0, 350, cd, cd);
            ellipse(450, 95, cd, cd);
            ellipse(170, 280, cd, cd);


        }

    }

}

below are some screen grabs of my working project, if for some reason the webcam isn’t working you can reference these! final 104 <- here is a zip file of my project as I am aware that it is not working on the WP.

John Baldessari is an artist who is most famous for his works where he took colored sticker dots and put them over the faces of people in photographs. This act is meant to be about erasure and obliteration. For my project I decided to flip that on its head and make it about erasing the background and focusing on the individuality. The duality of color (primary colors and their complement) are meant to emphasize individuality in humanity as wellBelow is a John Baldessari image to reference:

 

final project ARDEN WOLF

sketch.js


var d=0;
var x = 0;
var y = 0;
var  soundA;
var  soundB;
var  soundC;
var  soundD;
var  soundE;
var  soundF;
var  soundG;
var  soundH;
var  soundI;
var  soundJ;
var  soundK;
var  soundL;
var  soundM;
var  soundN;
var soundO;
var soundP;
var soundQ;
var soundR;
var soundS;
var soundT;
var soundU;
var soundV;
var soundW;
var soundX;
var soundY;
var soundZ;
var sound1;
var sound2;
var sound3;
var sound4;
var sound5;

var shape;

var objects= [];

function preload(){
    soundA = loadSound ("guitar.wav");
    soundB = loadSound ("sqeek1.wav");
    soundC = loadSound ("sqeek 2.wav");
    soundD = loadSound ("clap.wav");
    soundE = loadSound ("snare.wav");
    soundF = loadSound ("explosion.wav");
    soundG = loadSound ("shortGrainyDrum.wav");
    soundH = loadSound ("ambience.wav");
    soundI = loadSound ("laser.wav");
    soundJ = loadSound ("bang.wav");
    soundK = loadSound ("wind.wav");
    soundL = loadSound ("handclap.wav");
    soundM = loadSound ("bowl.wav");
    soundN = loadSound ("springy.wav");
    soundO = loadSound ("tom.wav");
    soundP = loadSound ("singing.wav");
    soundQ = loadSound ("music.wav");
    soundR = loadSound ("switchA.wav");
    soundS = loadSound ("pfft.wav");
    soundT = loadSound ("bang.wav");
    soundU = loadSound ("ooo.wav");
    soundV = loadSound ("sparkle.wav");
    soundW = loadSound ("gloop.wav");
    soundX = loadSound ("creepy.wav");
    soundY = loadSound ("space.wav");
    soundZ = loadSound ("drumBeat.wav");
    sound1 = loadSound ("clave.wav");
    sound2 = loadSound ("piano.wav");
    sound3 = loadSound ("razor.wav");
    sound4 = loadSound ("synthetic.wav");
    sound5 = loadSound ("alien.wav");
}


function setup() {
    createCanvas(400, 400);
    background(0);
    frameRate(10);
}

function makeRect(xX,yY,d){
    var s = { 
        width: d,
        height: d,
        x: xX,
        y: yY,
        draw: rectDraw,
        update:update

    }
    return s;
}


function makeEllipse(xX, yY, d){
   var  s = {
        width: d,
        height:d,
        x: xX,
        y: yY,
        draw: ellipseDraw,
        update:update
    }
    return s;

}

function rectDraw() {
    rect (this.x, this.y, this.width,this.height);
}

function ellipseDraw() {
    ellipse (this.x, this.y, this.width,this.height);
}

function update (){
    print(d); 
      if (this.width> 0){
        this.width = this.width - 30;
      }
      if (this.height>0){
        this.height = this.height - 30;
      }
}


function draw() {
    background(0); // background confetti
    strokeWeight(4);
    for (var x = 0; x < width; x = x + 1) {
        stroke(50);
        point(random(1,400) ,random(100,300) * sin(radians(x)));
        point(x, random(1,50) * cos(radians(x)));
    }
    noStroke();
    // if (millis() > 2000) {
    //     osc.stop();
    //     noLoop();
    // }
for (i = 0; i< objects.length; i++){
    objects[i].update();
    objects[i].draw();

}


if (keyIsPressed) {
    d=300;
    x = random(5,350);
    y = random(5,350);

    if (key === 'a'){
        fill(238,130,238);
        print(soundA);
        soundA.play();
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
       // shape = 0;

    }
    
    if (key === 'b') {
        fill(214);
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        //shape = 0;
        soundB.play();
    }

    if (key === 'c'){
        fill(0);
        //shape = 1;
        var rectangle= makeRect(x,y,d);
        objects.push(rectangle);
        soundC.play();
    }

    if (key === 'd'){
        fill(124,252,0);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundD.play();
    }

    if (key === 'e'){
        fill(0,255,255);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundE.play();
    }

    if (key === 'f'){
        fill(255,255,0);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundF.play();
    }

    if (key === 'g'){
        fill(139,0,0);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundG.play();
    }

    if (key === 'h'){
        fill(50,205,50);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundH.play();
    }

    if (key === 'i'){
        fill(51,51,255);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundI.play();
    }

    if (key === 'j'){
        fill(160,160,160);
        //shape = 1;
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundJ.play();
    }

    if (key === 'k'){
        fill(255);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundK.play();
    }

    if (key === 'l'){
        fill(51,0,102);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundL.play();
    }

    if (key === 'm'){
        fill(204,255,204);
        //shape = 0;
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundM.play();
    }

    if (key === 'n'){
        fill(255,0,127);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundN.play();
    }

    if (key === 'o'){
        fill(255,51,153);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundO.play();
    }

    if (key === 'q'){
        fill(204,255,153);
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundQ.play();
    }

    if (key === 'r'){
        fill(255,204,255);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundR.play();
    }

    if (key === 's'){
        fill(255,0,0);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundS.play();
    }

    if (key === 't'){
        fill(255,215,0);
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundT.play();
    }

    if (key === 'u'){
        fill(255,165,0);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundU.play();
    }

    if (key === 'v'){
        fill(254,0,246);
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundV.play();
    }

    if (key === 'w'){
        fill(1,30,254);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundW.play();
    }
    if (key === 'x'){
        fill(253,254,2);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundX.play();
    }

    if (key === 'y'){
        fill(254,0,0);
        var rectangle = makeRect(x,y,d);
        objects.push(rectangle);
        soundY.play();
    }

    if (key === 'z'){
        fill(204,255,0);
        var circle = makeEllipse(x,y,d);
        objects.push(circle);
        soundZ.play();
    }

  }
      print(d); 
      if (d > 0){
        d = d - 30;
      }

if (shape ==0){
     ellipse(x,y,d,d);
}

else {
    rectMode(CENTER);
    rect(x,y,d,d);
}
   

  } 

    


  

final project

Kyle Leve Final Project


One image from the animation


Another image from the animation

Final Project-Kyle Leve

My project is an interactive art form where a tree is decorated with ornaments in time with music playing in the background. The song that is playing is “Carol of the Bells” by the Trans Siberian Orchestra. However, since I used multiple js files for this project WordPress would not run the whole project. So I have attached a zip file to run all the files. Download and unzip the zip file. Then to look at the code, look at all the different js files. To look at the project, open the index. As long as the index is running in a browser that allows audio, the file should play correctly. Once the index is loaded, all that needs to be done to start the animation is click the mouse on the screen and the music should start playing.

Eunice Choe – Final Project

sketch

/*Eunice Choe
Section E
ejchoe@andrew.cmu.edu
Final Project*/

// options variable
var option = 1;

// scene 1
var Px = [];
var Py = [];
var Pdx = [];
var Pdy = [];
var newP = [];

// scene 2
var r = 220;
var g = 247;
var b = 255;
var cloud = [];
var landscape = 0.002;
var spot = [];
var flowers = [];

// scene 3
var img;

// spring constants (blinds pulling bar)
var springHeight = 32;
var left;
var right;
var maxHeight = 100;
var minHeight = 200;
var over = false;
var move = false;

// spring constants (main blinds)
var mass = 0.8;
var sConstant = 0.2;
var damping = 0.92;
var rest = 40;

// spring movement variables
var ps = rest;   // position
var vs = 0.0; // velocity
var as = 0;   // acceleration
var f = 0;    // force

//scene 4
var img4;
var input;
var analyzer;


function preload() {
    img = loadImage("https://i.imgur.com/IdD3GJq.png");
    img4 = loadImage("https://i.imgur.com/sR307j6.png?2");
}

function setup(){
    createCanvas(480, 300);
// initializing floating particles
    for (i = 0; i < 100; i++) {
        Px[i] = random(480);
        Py[i] = random(300);
        Pdx[i] = random(-5, 5);
        Pdy[i] = random(-5, 5);
    }
    frameRate(10);

    push();
    angleMode(DEGREES);
    // initial collection of flowers and clouds
    for (var i = 0; i < 10; i++) {
        var cloudX = random(width);
        var rx = random(width);
        cloud[i] = makeCloud(cloudX);
        flowers[i] = makeFlowers(rx);
    }

// initializing lefts and rights for spring
    left = width/2 - 150;
    right = width/2 + 150;

// initializing audio input
    input = new p5.AudioIn();
    input.start();
}

function draw() {
    background(220, 247, 255);
    noStroke();
// scene 1
    if (option == 1){
        scene1();
    }
// scene 2
    else if (option == 2) {
        scene2();
    }
// scene 3
    else if (option == 3) {
        scene3();
    }
// scene 4
    else if (option == 4) {
        scene4();
    }
}

function scene1() {
    translate(width / 2, height / 2);
// flower petals
    for (var i = 0; i < 20; i ++) {
        fill(255, 224, 122, 90);
        ellipse(0, 30, 100, 500);
        rotate(PI * 8);
  }
// flower center
    for (var i = 0; i < 10; i ++) {
        fill(84, 46, 13, 80);
        ellipse(0, 0, 100, 200);
        rotate(PI * 8);
  }
// floating particles
    for (i = 0; i < 500; i++) {
        fill(255, 90);
        ellipse(Px[i], Py[i], 10, 10);
        Px[i] += Pdx[i];
        Py[i] += Pdy[i];
    }
}

function scene2(){
    background(r, g, b);
    if (mouseX > 0 & mouseX < width) {
        r = 229 - mouseX / 20;
        g = 247 - mouseX / 50;
        b = 224 + mouseX / 20;
    }
// grass in the back; randomizes when page refreshed
    beginShape();
    fill(139, 189, 125);
    vertex(0, height);
    for (var x = 0; x < width; x++) {
        var t = x * landscape;
        var y = map(noise(t), 0, 1, 0, height / 2);
        vertex(x, y + 100);
    }
    vertex(width, height);
    endShape();
    updateFlowers();
// rain when mouse is pressed
    if (mouseIsPressed) {
        frameRate(90);
        fill(255);
        spot.x = random(width);
        spot.y = random(height);
        ellipse(spot.x, spot.y, 5, 70);
    }
// clouds
    for (var i = 0; i < cloud.length; i++) {
        cloud[i].draw();
        cloud[i].move();
    }
}

function scene3() {
    image(img, 0, 0);
    fill(156, 38, 27);
    rect(0, 0, 100, height);
    rect(380, 0, 100, height);
    rect(100, 0, 280, 40);
    rect(100, 260, 280, 40);
    fill(242, 235, 202);
    rect(90, 270, 300, 10);
    fill(201, 196, 168);
    quad(100, 260, 380, 260, 390, 270, 90, 270);
    stroke(74, 89, 79);
    noFill();
    strokeWeight(10);
// sky gets darker when mouse is in window
    if ((mouseX > 100) & (mouseX < 380) &&
        (mouseY > 40) && (mouseY < 260)) {
        fill(43, 29, 133, 50);
    }
    rect(100, 40, 280, 220);
    updateSpring();
    drawSpring();
}

function scene4() {
    image(img4, 0, 0);
    push();
    var volume = input.getLevel();
// if the volume of the sound goes above threshold, then a firefly will appear
// fireflies are at random positions and their sizes reflect the volume
    var threshold = 0.05;
    if (volume > threshold) {
        push();
        frameRate(10);
        noStroke();
        fill(199, 255, 57);
        ellipse(random(width), random(170, height), volume * 50, volume * 50);
        pop();
    }
    fill(161, 156, 125);
    rect(40, 120, 60, 145);
    pop();
}

function updateFlowers() {
    // Update the flowers positions; random when page refreshed
    for (var i = 0; i < flowers.length; i++){
        flowers[i].display();
    }
}

function flowersDisplay() {
    var floorHeight = 10;
    var bHeight = this.nFloors * floorHeight * 2;
    noStroke();
    push();
    translate(this.x, height);
    fill(204, 187, 145);
    rect(0, -bHeight, this.breadth, bHeight);
    noStroke();
    translate(0, -bHeight);
    for (var i = 0; i < 20; i ++) {
        fill(255, 224, 122, 90);
        ellipse(0, 30, 20, 50);
        rotate(PI * 8);
    }
    fill(84, 46, 13, 90);
    ellipse(0, 0, 30, 30);
    pop();

}

function makeFlowers(birthLocationX) {
    var fl = {x: birthLocationX,
             breadth: 5,
             nFloors: round(random(2,8)),
             display: flowersDisplay}
    return fl;
}

function cloudDraw() {
    push();
    translate(this.xPos, this.yOffset);
    stroke(255, 255, 255, 70);
    strokeWeight(this.cHeight);
    line(0, 0, this.cSize, 0);
    pop();
}

function cloudMove() {
    this.xPos += this.speed;
    if(this.xPos < 0 - this.cSize - 30) {
        this.cHeight = random(10, 50);
        this.cSize = random(30, 150);
        this.xPos = width + this.cSize + random(-25, 25);
    }
}

function makeCloud() {
    var cloud = {xPos: random(width), //, width*4
                speed: random(-3, -1),
                cSize: random(30, 150),
                cHeight: random(20, 60),
                yOffset: random(50, height),
                draw: cloudDraw,
                move: cloudMove};
    return cloud;
}

function drawSpring() {
// draw main cream blinds
    noStroke();
    fill(255, 251, 243);
    rect(100, ps + springHeight, 280, - height);
    var baseWidth = 20;
    push();
    rectMode(CORNERS);
// if mouse is over gray bar, turn white
    if (over || move) {
        fill(255);
    } else {
        fill(204);
    }

    rect(left, ps, right, ps + springHeight);
    pop();
}

function updateSpring() {
// update the spring position
    if (!move) {
        f = -sConstant * ( ps - rest );
        as = f / mass; // acceleration
        vs = damping * (vs + as); // velocity
        ps = ps + vs;        // updated position
    }

    if (abs(vs) < 0.1) {
        vs = 0.0;
    }

  // see if mouse is over bottom bar
    if (mouseX > left & mouseX < right && mouseY > ps && mouseY < ps + springHeight) {
        over = true;
    } else {
        over = false;
    }

// constrain position of bottom bar
    if (move) {
        ps = mouseY - springHeight/2;
        ps = constrain(ps, minHeight, maxHeight);
    }
}

function mousePressed() {
    if (over) {
        move = true;
    }
}

function mouseReleased() {
    move = false;
}

// move through 4 slides
function keyPressed() {
    option++;
    if (option > 4) option = 1;
}

My final project is based off of a book I enjoyed from childhood called Zoom, by Istvan Banyai. I tried to replicate a small glimpse of the premise of the book, which is to keep zooming out as each page is turned. My project starts off with a zoomed in sunflower and it eventually zooms out to a house. In my project, I wanted to make the zoom outs seem less static, so I incorporated movement and interactions in each scene. Some interactions include clicking for a spring effect, pressing for rain, moving the mouse around for color changes, and making sounds for objects to appear.

Instructions:
Press any key to move on to the next scene.

Scene 1 shows a zoomed in flower with floating particles.
Scene 2 zooms out to show more flowers in randomized positions. The color of sky changes depending on mouse position and it starts to rain when the mouse is pressed.
Scene 3 zooms out to a window view of the flowers. when the mouse is in the window, the sky gets darker. Also when the gray bar is clicked, the curtain gives a spring effect.
Scene 4 zooms out to outside the house. The interaction is based off of sound, so if there is a loud sound, fireflies will appear in random positions.

Jessica Timczyk – Final Project

Final Project

// Jessica Timczyk
// Section D
// jtimczyk@andrew.cmu.edu
// Final-Project

///////// GLOBAL VARIABLES ///////////
var terrainDetail = 0.005;
var intercols = [];

/////// snow globals //////
var snow = [];
var gravity;
var zOff = 0;
var mt = [];

///// elephant globals //////
var frames = []; // store images
var frameIndex = 0;
var system; // particle system for elephants water
var trunkUp = false;
var counter = 0;
var click = -1;

//////// sound globals ////////
var elephantSound;
var birdSound;
var tigerSound;

///////// water waves globals /////////////
var t = 0;

///////// bush globals //////////////
var bush;
var bush1y= 240;

var bush2y = 350;

function preload() {
    ////////////////// ELEPHANT IMAGE PRELOADS ////////////////
    // urls for each elephant image of movement cycle
    var filenames = [];
    filenames[0] = "https://i.imgur.com/PSJnCjQ.png";
    filenames[1] = "https://i.imgur.com/PbWyeNh.png";
    filenames[2] = "https://i.imgur.com/s0o7oWG.png";

    // stores each picture into an array
    for (var i = 0; i < 3; i++) {
        frames[i] = loadImage(filenames[i]);
    }

    ////////////////// BUSH PRELOADS ////////////////////
    bush = loadImage("https://i.imgur.com/jdxSCfo.png");

    ////////////////// SOUND PRELOADS //////////////////
    elephantSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/139875__y89312__44-1.wav");
    elephantSound.setVolume(0.5);
    birdSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/238144__m4d3r0__small-bird-jungle-sounds-v3-2.wav");
    birdSound.setVolume(0.5);
    tigerSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/439280__schots__angry-tiger-4.wav")
    tigerSound.setVolume(0.5);
}



function setup() {
    createCanvas(600, 400);
    background(219, 245, 250);


    ////////////// MOUNTAIN SET UP /////////////
    for (var x = 0; x < width; x++) { // createse a random static mountain range using noise every time refreshed
        var t = (x * terrainDetail) 
        var y = map(noise(t), 0,1, 0, height/ 1.5);
        mt.push([x,y,height]); // pushes the array into the mt array
    }

    //////////// ELEPHANT WATER PARTICLE SYSTEM ///////////
    system = new ParticleSystem(createVector(260, 230)); // creates a particle system for the elephants water

    //////////// SNOWFLAKE SET UP ////////////
    gravity = createVector(0, 0.2); // gravity vector
    for (var i = 0; i < 200; i++){ // creates the 200 snowflakes and gives them random starting positions
        var x = random(width);
        var y = random(height);
        snow.push(new Snowflake(x,y)); // pushes new snowflake into the array
    }
}

function draw() {
    background(25, 28, 84);

    drawNorthernLights(); 

    drawScenary();

    drawTrees();

    drawBush();

    ////////////////// ELEPHANT /////////////////////
    drawElephant();
    if (frameIndex === 2) { // water comes out of his trunk when its in the up position
            elephantWater();
        }
    if (mouseIsPressed & trunkUp == false && mouseX > 150 && mouseX < 300 && mouseY > 190 && mouseY < 350 && (click%2 === 0)) { // if mouse pressed on elephant trunk moves up
        counter = 0
        trunkUp = true
        }
    if (trunkUp == true) {
        moveUp()
    }
    if (mouseIsPressed && counter > 32 && (click%2 != 0) && mouseX > 150 && mouseX < 300 && mouseY > 190 && mouseY < 350) { // when the elephant is clicked a second time it puts and keeps trunk down
            counter = 0;
            frameIndex = 0;
            trunkUp = false;
    }

    drawTrees2(); // second set of trees that are infront of the elephant

    drawBush2(); // second set of bushes that are infront of elephant
     if (mouseX > 400 & mouseX < 480 && mouseY > 220 && mouseY < 260) { // the bush hops when mouse is scrolled over it
        bush1y += random(-5, 5);
    }
    if (mouseX > 30 & mouseX < 130 && mouseY > 345 && mouseY < 385) { // the bush hops when mouse is scrolled over it
        bush2y += random(-5, 5);
    }
   
  



    ////////////////// DRAWING SNOWFLAKE /////////////

    zOff += 0.01; // z offset

    for (flake of snow) { //the position, gravity and wind forces are unique to each snowflake
        var xOff = flake.pos.x / width;
        var yOff = flake.pos.y / height;
        var wAngle = noise(xOff, yOff, zOff) * TWO_PI;
        var wind = p5.Vector.fromAngle(wAngle);
        wind.mult(0.2);
        flake.applyForce(gravity);
        flake.applyForce(wind);
        flake.update();
        flake.render();
    }
  

    mySounds(); // plays sounds

}

function drawScenary() {

    /////////// MOUNTAINS /////////////
    stroke(76, 86, 109); // Grey color of mountains
    noFill();
    beginShape(); 
    for (var x = 0; x < width; x++) { // createse a random static mountain range using noise every time refreshed
        line(mt[x][0], mt[x][1], mt[x][0], mt[x][2]); 
    }
    endShape();
    
    ////////////// GROUND ///////////////
    noStroke();
    fill(196, 157, 112);
    rect(0, height / 2 + 20, width, height / 2 - 20);

    /////////// POND ///////////////
    noStroke();
    fill(69, 156, 223);
    ellipse(width - 40, height - 60, 500, 150);


}

///////////////////// BUSHES ///////////////////////
function drawBush() { // draws bush images that sit behind the elephant
  

    imageMode(CENTER);
    image(bush, 440, bush1y, 150, 70); // variable so that it wiggles up and down
    image(bush, 320, 260, 150, 70);
    image(bush, 85, 240, 190, 70);

   
}

function drawBush2() { // draws bush images that sit infront of the elephant
    imageMode(CENTER);
    image(bush, 310, 380, 180, 70); 
    image(bush, 70, bush2y, 150, 70); // variable so that bush shakes when moused over
}

/////////////////// ELEPHANT /////////////////////
function drawElephant() { // elephant picture
    imageMode(CENTER);
    image(frames[frameIndex], 230, 270, 200, 200);
}


function moveUp() { // moves trunk all the way up when clicked once
    if (click%2 == 0) { // when the elephant is clicked an odd time the trunk just goes down
        counter += 1;
        if (counter == 15) {
            frameIndex = 1;
        }
        if (counter == 30) {
            frameIndex = 2;
        }
    } 
}

function mousePressed() { // increases click count when mouse is pressed once and mouse on elephant
if (mouseX > 150 & mouseX < 300 && mouseY > 190 && mouseY < 350){
    click += 1;
    }
}

function elephantWater() { // run particle system
    system.addParticle();
    system.run();
}

// simple particle class
var Particle = function(position) {
    this.acceleration = createVector(0, 0.05);
    this.velocity = createVector(random(-1, 1), random(-1, 0));
    this.position = position.copy();
    this.lifespan = 255;
}

Particle.prototype.run = function() {
    this.update();
    this.display();
}

// updating position
Particle.prototype.update = function() {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
    this.lifespan -= 2;
}

// display method for particles
Particle.prototype.display = function() {
    stroke(190, 244, 250, this.lifespan);
    strokeWeight(2);
    fill(143, 239, 250, this.lifespan);
    ellipse(this.position.x, this.position.y, 12, 12);
}

// check if particle is still useful
Particle.prototype.isDead = function() {
    return this.lifespan < 0;
}

var ParticleSystem = function(position) { // position of particles
    this.origin = position.copy();
    this.particles = [];
}

ParticleSystem.prototype.addParticle = function() { // pushes a new particle into the system at the starting point
    this.particles.push(new Particle(this.origin));
}

ParticleSystem.prototype.run = function() { // gets rid of particles that have expired
    for (var i = this.particles.length-1; i >= 0; i--) {
        var p = this.particles[i];
        p.run();
        if (p.isDead()) {
            this.particles.splice(i, 1);
        }
    }
}


////////////////// TREES ////////////////////////
function drawTrees() { // trees that are positioned begind elephant
    push();
    translate(550, 250);
    drawBranch(0, map(mouseY, 0, 400, 15, 20));
    pop();

    push();
    translate(150, 250);
    drawBranch(0, map(mouseY, 0, 400, 15, 20));
    pop();

    push();
    translate(100, 290);
    drawBranch(0, map(mouseY, 0, 400, 15, 20));
    pop();
}

function drawTrees2() { // trees that are positioned in front of elephant also rotate opposite way
    push();
    translate(100, 350);
    drawBranch2(0, map(mouseY, 0, 400, 15, 20));
    pop();

    push();
    translate(500, 260);
    drawBranch2(0, map(mouseY, 0, 400, 15, 20));
    pop();

}

function drawBranch2(depth, len) { // same as drawtree but these trees are positioned infront of the elephant
    strokeWeight(depth / 3 + 1);
    stroke(random( 15, 180), random(100, 244), random(10, 100)); // continuously changing green color
    line(0, 0, 0, -len);
    push();
    translate(0, -len);
    drawTree2(depth + 1, len);
    pop();
}

function drawTree2(depth, len) { // same as drawtree but these trees are positioned infront of the elephant
    if (depth < 8) {
        rotate(radians(map(mouseX, 400, 0, -5, 5))); // allows trees to rotate with mouse
        drawBranch2(depth, len);
        rotate(radians(30));
        drawBranch2(depth, len);
    }
}

function drawBranch(depth, len) { // idividual branch details
    strokeWeight(depth / 3 + 1);
    stroke(random( 15, 180), random(100, 244), random(10, 100)); // continuously changing green color
    line(0, 0, 0, -len);
    push();
    translate(0, -len);
    drawTree(depth + 1, len);
    pop();
}

function drawTree(depth, len) { // draws the two sides of the tree branches
    if (depth < 8) {
        rotate(radians(map(mouseX, 0, 400, -30, -20))); // allows trees to rotate with mouse
        drawBranch(depth, len);
        rotate(radians(30));
        drawBranch(depth, len);
    }
}

////////////////// NORTHERN LIGHTS ///////////////////
function drawNorthernLights() {
    noStroke();
    fill(random( 15, 180), random(10, 100), random(100, 244), 190); // make colors change and transparent to look like northern lights

  // make a x and y grid of circles
  for (let x = 0; x <= width; x = x + 30) {
    for (let y = 0; y <= height / 2 + 20; y = y + 30) {

      // starting point of each circle depends on mouse position
      let xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, true);
      let yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, true);

      // also varies based on the particle's location
      let angle = xAngle * (x / width) + yAngle * (y / height);

      // each particle moves in a circle
      let myX = x + 20 * cos(2 * PI * t + angle);
      let myY = y + 20 * sin(2 * PI * t + angle);

      ellipse(myX, myY, 10); // draw particle
    }
  }

  t = t + 0.01; // update time
}

////////////////// SNOWFLAKES ///////////////////

function getRandomSize() { // makes a randomly sized snowflake that is more likely to be smaller
    var r = pow(random(0, 1), 5);
    return constrain(r * 32, 2, 36);
}

class Snowflake { 

    constructor() { // snowflake object
        var x = random(width);
        var y = random(-100, -10);
        this.pos = createVector(x, y);
        this.vel = createVector(0, 0);
        this.acc = createVector();
        this.angle = random(TWO_PI);
        this.dir = (random(1) > 0.5) ? 1 : -1;
        this.xOff = 0;


        this.r = getRandomSize(); // random sizr of snowflakes
    }

    applyForce(force) {
        // parallax effect hack
        var f = force.copy();
        f.mult(this.r);

        this.acc.add(f); // add acceleration force
    }

    randomize() { // gives flakes a random starting poisiton above the canvas
        var x = random(width);
        var y = random(-100, -10);
        this.pos = createVector(x, y);
        this.vel = createVector(0, 0);
        this.acc = createVector();
        this.r = getRandomSize();
    }

    update() { // updates positions, speeds, angles and etc of snow

        this.xOff = sin(this.angle * 2) * 2 * this.r; // sine wave making snow move in addition to perlin noise

        this.vel.add(this.acc);  // velocity calculations
        this.vel.limit(this.r * 0.2);

        if (this.vel.mag() < 1) {
            this.vel.normalize();
        }

        this.pos.add(this.vel);
        this.acc.mult(0);

        if (this.pos.y > height + this.r){ //gives them a new random position when they reach the bottom of the screen
            this.randomize();
        }

        // flakes wrap left and right
        if (this.pos.x < -this.r) {
            this.pos.x = width + this.r;
        }

        this.angle += this.dir * this.vel.mag() / 200; // spin of flakes goes different directions, also dependent on their speed
    }

    render(){ // draw the snowflakes
        stroke(255);
        push();
        strokeWeight(this.r);
        translate(this.pos.x + this.xOff, this.pos.y);
        point(0, 0);
        pop();
    }
}


function mySounds() {
    // elephant sound
    // plays sound when elephants clicked on and only when trunk us down
    if (mouseIsPressed & mouseX > 150 && mouseX < 300 && mouseY > 190 && mouseY < 350 && click%2 == 0) {
        elephantSound.play();
    }

    // bird sound
    // plays sound when bush is clicked on
    if (mouseIsPressed & mouseX > 30 && mouseX < 130 && mouseY > bush2y - 20 && mouseY < bush2y + 20) {
        birdSound.play();
    }

    // tiger sound
    // plays sound when bush is clicked on
    if (mouseIsPressed & mouseX > 400 && mouseX < 480 && mouseY > bush1y - 20 && mouseY < bush1y + 20) {
        tigerSound.play();
    }
}













After following the instructions for uploading sounds onto WP, my program will run perfectly but the sounds for some reason are still not working. Therefore, I have additionally included a zip of my final project so that you can see the working sounds. All you need to do is unzip the file and open it using a local server. After troubleshooting many times, I am still unsure why the sound will not work over WordPress. Final Project

I really enjoyed doing this project, it forced me to use new techniques and functions that I never had before. I really wanted this to be an interactive picture, using many complex computations to make things move and etc.