// 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.