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.

Leave a Reply