Victoria Reiter Final Project

sketch

/*
Victoria Reiter
vreiter@andrew.cmu.edu
Section B
Final Project
*/

var mapImage; // loads map background
var toggledOn; // makes country bio appear
var countryVicinity; // maximum distance possible between mouseX/Y and country position
var countries = []; // array to contain all countries
var whichSelected; // array value of selected country

// preloads map image background
function preload() {
    mapImage = loadImage("https://i.imgur.com/z6ty1Bi.png");
}

// creates each country as an object and pushes them into an array
// each country has a color, location, and image it will pop up with
function setup() {
    createCanvas(1300, 659);
    background(220);

    var america = {
        color: color(255, 255, 191),
        x: 120,
        y: 200,
        img: loadImage("https://i.imgur.com/8SMqOU4.jpg2")
    }
    countries.push(america);

    var argentina = {
        color: color(8, 104, 172),
        x: 360,
        y: 550,
        img: loadImage("https://i.imgur.com/Nk7xX52.jpg")
    }
    countries.push(argentina);

    var chile = {
        color: color(8, 64, 129),
        x: 320,
        y: 570,
        img: loadImage("https://i.imgur.com/WxdaXfL.jpg")
    }
    countries.push(chile);

    var uruguay = {
        color: color(43, 140, 190),
        x: 420,
        y: 544,
        img: loadImage("https://i.imgur.com/tp7dzBB.jpg")
    }
    countries.push(uruguay);

    var peru = {
        color: color(78, 179, 211),
        x: 340,
        y: 455,
        img: loadImage("https://i.imgur.com/sielvnG.jpg")
    }
    countries.push(peru);

    var germany = {
        color: color(33, 102, 172),
        x: 620,
        y: 200,
        img: loadImage("https://i.imgur.com/FVOB4HK.jpg")
    }
    countries.push(germany);

    var france = {
        color: color(54, 144, 192),
        x: 550,
        y: 230,
        img: loadImage("https://i.imgur.com/ha2K51p.jpg")
    }
    countries.push(france);

    var italy = {
        color: color(166, 189, 219),
        x: 640,
        y: 230,
        img: loadImage("https://i.imgur.com/HNDsgLP.jpg")
    }
    countries.push(italy);

    var britain = {
        color: color(5, 112, 176),
        x: 565,
        y: 175,
        img: loadImage("https://i.imgur.com/D7O2fRO.jpg")
    }
    countries.push(britain);

    var australia = {
        color: color(190, 186, 218),
        x: 1105,
        y: 530,
        img: loadImage("https://i.imgur.com/CgUYnxQ.jpg")
    }
    countries.push(australia);

    var newZealand = {
        color: color(142, 56, 142),
        x: 1235,
        y: 595,
        img: loadImage("https://i.imgur.com/yxATqNk.jpg")
    }
    countries.push(newZealand);

    var cameroon = {
        color: color(129, 15, 124),
        x: 650,
        y: 400,
        img: loadImage("https://i.imgur.com/emVJlxl.jpg")
    }
    countries.push(cameroon);

    var nicaragua = {
        color: color(2, 56, 88),
        x: 300,
        y: 363,
        img: loadImage("https://i.imgur.com/4A0bQxr.jpg")
    }
    countries.push(nicaragua);

    var canada = {
        color: color(4, 90, 141),
        x: 260,
        y: 125,
        img: loadImage("https://i.imgur.com/y1fFIh0.jpg")
    }
    countries.push(canada);

    var moldova = {
        color: color(158, 80, 170),
        x: 715,
        y: 220,
        img: loadImage("https://i.imgur.com/fJimQz7.jpg")
    }
    countries.push(moldova);

    var spain = {
        color: color(116, 169, 207),
        x: 585,
        y: 250,
        img: loadImage("https://i.imgur.com/KXOKjpW.jpg")
    }
    countries.push(spain);

    var china = {
        color: color(146, 197, 222),
        x: 975,
        y: 265,
        img: loadImage("https://i.imgur.com/Tjr5PL6.jpg")
    }
    countries.push(china);

    var haiti = {
        color: color(141, 10, 135),
        x: 220,
        y: 330,
        img: loadImage("https://i.imgur.com/VhYa9Fp.jpg")
    }
    countries.push(haiti);

    var hongKong = {
        color: color(74, 126, 195),
        x: 975,
        y: 330,
        img: loadImage("https://i.imgur.com/jvpeMbE.jpg")
    }
    countries.push(hongKong);

    var indonesia = {
        color: color(152, 78, 163),
        x: 1040,
        y: 430,
        img: loadImage("https://i.imgur.com/rdBJk16.jpg")
    }
    countries.push(indonesia);

    var nepal = {
        color: color(140, 107, 177),
        x: 910,
        y: 300,
        img: loadImage("https://i.imgur.com/HOfUeU2.jpg")
    }
    countries.push(nepal);

    var ecuador = {
        color: color(158, 188, 218),
        x: 300,
        y: 430,
        img: loadImage("https://i.imgur.com/gEO6bcG.jpg")
    }
    countries.push(ecuador);
}

function draw() {
    image(mapImage, 0, 0);
    
    // rectangle pop up of information will pop up if toggledOn is turned on
    if (toggledOn) {
        image(countries[whichSelected].img, 200, 25, width - 400, height - 25);

    }
}

// based on location and pixel color, the specific country will be identified
function mousePressed() {
    toggledOn = false;
    countryVicinity = 200;
    var colorAtMouseX = mapImage.get(mouseX, mouseY);
    var transformedColorAtMouseX = color(colorAtMouseX[0], colorAtMouseX[1], colorAtMouseX[2], colorAtMouseX[3]); 
    //whichSelected = what? your if statement is essentially going to check which item in the array of countries is the right one!
    for(var i = 0; i < countries.length; i++) {
        if ((dist(countries[i].x, countries[i].y, mouseX, mouseY) < countryVicinity)) {
            // print((countries[i].color).toString());
            // print((transformedColorAtMouseX).toString());
            if ((countries[i].color).toString() == transformedColorAtMouseX.toString()) {
                whichSelected = i;
                toggledOn = true;
            }
        }

    }
}

My final project! An interactive map of places I’ve been and places where I know people from. Click a country and explore what I’ve explored!

Lingfan Jiang & Kai Zhang – Final Project

sketch

//Lingfan Jiang/ Kai Zhang
//Section B
//lingfanj@andrew.cmu.edu / kaiz1@andrew.cmu.edu
//final project

//bird variables
var g = 0.5;
var v = 0;
//upforce
var Fup = 20;
var birdx = 120;
var birdy = 240;
//pipe
var pipes = [];
var currentPipeY;
var gap = 170;
//counter
var successC = 0;
//lean degrees
var gameOn = true;
//terrain
var terrainDetail = 0.002;
var terrainSpeed = -0.001;
//clouds
var clouds = [];
var cloudsx = [];
var cloudsy = [];
var cloudsSpeed = -0.5;
var cloudsSize = [];

var gameOn = true;

var totalTime;
//board content
var level = ["Bronze", "Silver", "Gold", "Platinum", "Diamond", "Master", "王者!"]
var newcolor = ["green", "pink", "gold", "orchid", "tan", "grey", "white"]
var numbercount;


function setup() {
    createCanvas(640,480);
    frameRate(80);
    pipes.push(makePipes()); 
}


function draw() {


    background(170, 237, 239);

    //create cloud objects
    updateAndDisplayclouds();

    terrain();

    updateAndDisplayPipes();

    drawBird(birdx, birdy);

    controlBird();

    //create pipe each 80 frames
    if (frameCount % 90 == 0 & gameOn) {
        pipes.push(makePipes());
    }

    if (pipes.length != 0) {
        //remove the already gone pipes
        if (pipes[0].x < -50) {
            pipes.shift();
        }

        //hit test
        if (pipes[0].x < birdx + 18 & pipes[0].x + 30 > birdx - 18) {
            if (birdy - 15 < pipes[0].gapY || birdy + 15 > pipes[0].gapY + gap) {
                //hit indicator
                fill("red");
                ellipse(birdx + 5, birdy, 30, 30);
                //make the pipes stop
                for (var i = 0; i < pipes.length; i++) {
                    pipes[i].speed = 0;
                }
                gameOn = false;

                //game over content
                textAlign(CENTER);
                textSize(50);
                fill("orange");
                text("GAME OVER", width / 2, height / 2);
                fill("orange");
                push();
                rectMode(CENTER);
                textSize(18);
                rect(320, 300, 100, 50);
                fill(255);
                noStroke();
                text("RESTART", 321, 307);
                pop();

                //add score
                } else if (pipes[0].x == birdx - 2) {
                successC ++;
            }
        }
    }


    drawBoard();
}

////////////////////////////////
function controlBird(){
    v += g;
    birdy += v;

    //make the bird stop when it hits the bottom or the top
    if (birdy > height & gameOn) {
        birdy = height;
        v = 0;
    }
    else{
        birdy = birdy;
    }

    if (birdy < -30) {
        birdy = -30;
        v = 0;
    }
}

function updateAndDisplayclouds(){
    for (var n = 0; n < 8; n ++) {
        cloudsx.push(-150, random(width) + 150);
        cloudsy.push(random(40, 100));
        cloudsSize.push(random(80, 140));

        clouds[n] = makeClouds(cloudsx[n], cloudsy[n], cloudsSize[n]);
        clouds[n].cdraw();
        cloudsx[n] += cloudsSpeed;
        if (cloudsx[n] < -100) {
            cloudsx[n] = random (width + 100, width + 150);
        }
    }
}

function drawBird(x, y) {
    push();
    translate(x, y);
    angleMode(DEGREES);
    rotate(1.5 * v);
    fill("yellow");
    ellipse(0, 0, 36, 30);
    fill("white");
    ellipse(0 + 9, 0 - 5, 15, 15);
    ellipse(0 - 15, 0, 17, 8);
    fill("black");
    ellipse(0 + 13, 0 - 6, 5, 5);
    fill("orange");
    ellipse(0 + 10, 0 + 8, 20, 8);
    ellipse(0 + 10, 0 + 2, 20, 8);
    pop();
}

function drawBoard(){
    noFill();
    strokeWeight(2);
    stroke(0);
    rect(10, 10, 140, 46);
    noStroke();
    fill(0);
    textSize(18);
    textAlign(CENTER);
    text("Score: " + successC, 80, 30);
    text("Level: " + level[numbercount], 80, 48);
    strokeWeight(1);
    stroke(0);
}


function keyPressed() {
    if (key === " " & gameOn) {
        v -= Fup;
        //set up a maximum speed for the bird
        if (v < -10) {
        v = -10;
        }
    }
}


function mouseClicked() {
    //reset the game when the game is over
    if (mouseX > 270 & mouseX < 370 && mouseY > 275 && mouseY < 325 && gameOn == false) {
        pipes = [];
        gameOn = true;
        successC = 0;
    }
}


function makePipes() {
    var pipe = {
        x: 640,
        gapY: random(50, height - gap - 40),
        pwidth: 50,
        speed: 2,
        move: pipeMove,
        draw: pipeDraw,
        col: "green"
    }
    return pipe;
}


function pipeDraw() {
    //change the color and level when the score gets higher
    numbercount = floor(successC / 5);
    if (numbercount > 6) {
        numbercount = 6;
    }
    fill(newcolor[numbercount]);
    push();
    translate(this.x, 0);
    rect(0, -10, this.pwidth, this.gapY);
    rect(-3, this.gapY - 30, this.pwidth + 6, 30);
    rect(0, this.gapY + gap, this.pwidth, height - this.gapY - gap + 10);
    rect(-3, this.gapY + gap, this.pwidth + 6, 30);

    strokeWeight(5);
    stroke(255);
    line(10, 10, 10, this.gapY - 40);
    line(10, 470, 10, this.gapY + gap + 40);

    line(7, this.gapY - 10, 7, this.gapY - 20);
    line(7, gap + this.gapY + 10, 7, gap + this.gapY + 20);
    pop();
}


function pipeMove(){
    this.x -= this.speed;
}


function updateAndDisplayPipes() {
    for (var i = 0; i < pipes.length; i++) {
        pipes[i].move();
        pipes[i].draw();
    }
}


function terrain() {
    push();
    stroke(135, 210, 167);

    for (var q = 0; q < width; q++) {
        var t = (q * terrainDetail) - (millis() * terrainSpeed / 10);
        var y = map(noise(t), 0, 1 , height / 2 - 40, height - 50);
        line(q, y, q, height);
    }
    pop();

}

function makeClouds(x, y, size) {
    var cloud = {"cx": x, "cy": y, "csize": size, "cdraw": cloudDraw};
    return cloud;
}

function cloudDraw() {
    push();
    noStroke();
    fill(255);
    ellipse(this.cx, this.cy, this.csize, this.csize * 0.7);
    pop();
}

Introduction:

For our group final project, we decided to recreate the once viral game on mobile platforms – Flappy Birds, back in 2013. I(Kai) still recall how I would spend hours playing the game and tried to master it. Unfortunately, the game was removed from App Store because of it being “too addictive”. Up till now, I still have the game on my phone, despite it was too old for my current operating system. In order to experience a very unique game again, we tried to take a shot to develop the game.

 

Development Process:

First of all, Lingfan started to build the basic framework of the game, by creating an object “the bird” that will rise as we press the space button using basic physics, along with an array of tubes as objects that show up as time lapsed from right end of the canvas. Then I’ve taken over the file. I first used primitive geometries to create the tubes and the bird so they resemble the original look of the game. Also I’ve created the background and clouds that moved along with the camera panned, of course, of a much slower speed. As a next step, I started working on the “collision” moments when bird hit the tube. The logic is when the x position of tube passes through the location of the bird, the program determines if the bird is in between the gap of the tubes. If not, the tube turned grey, and an indicator would show up and informed the player the bird has hit the tube. The game was pretty much playable at this point, but we still need a reward/failure system, otherwise the game would run forever, even if the bird hits the tube. Lingfan then took over the file again and created it. He set a Boolean that determines if the game is over or not, which changes its value from true to false as it hits the tube. And then a button was created to restart the game. Every time the bird hits the tube, it would fall and we’ll see the “GAME OVER” appearing at the center of the screen. After the restart button is clicked, the code wipes the existing tubes array and brings back the bird so we can replay the game. As a final step, we worked together to clean up the code and further polish the game, including adding the score counter, a game rank indicator that tells you how good you are playing this game, the change of tube colors as you promote to the next level, the 3-dimensional look of the tube, etc. As this point, the game was pretty much finished.

 

Reflections:

One of the surprises about the game we’ve created is how it felt so close to the original game as we are playing. And during the development of the game, we’ve taken advantage of most skills that we acquired during the semester, so we got to practice pretty much everything again. Please go ahead and give it a try, and we hope you will enjoy the game as much as we do.

 

Game instruction:

Simply tap the space key so the bird rises to avoid the tube and earn 1 point each time the bird flies past a gap. You will get to the next level of the rank every time you successfully passed 5 tubes. (We tried to make it a little easier and more rewarding for you, as the original game was pretty hard to beat.)

Tanvi Harkare – Final Project

tanviharkare_sketch

//position of ball
var px = 100;
var py = 100;
var yvel = 4;
var ox = 400;
var bs = 30;

var r = 100;
var rx = 200;
var count = 0;
var score = 0;
var hscore = 0;

var obspeed = 2;

var terrainSpeed = 0.0005;
var terrainDetail = 0.005;
var terrainSpeed2 = 0.0002;
var terrainDetail2 = 0.002;


function preload() {
    mySnd = loadSound("boing.wav");
    mySnd.setVolume(0.5);
}
// to play the sound from within draw() or anywhere:

function setup(){
    createCanvas(400, 400);
    frameRate(30);
}

function draw(){
    background(255);
    py -= yvel;
    yvel -= 0.3;

    for (var x = 0; x < width; x++) {
        stroke(243, 184, 141);
        var t = (x * terrainDetail) + (millis() * terrainSpeed);
        var y = map(noise(t), 0,1, 0, height);
        line(x, y, x, height); 
        stroke(143, 61, 75);
        var t2 = (x * terrainDetail2) + (millis() * terrainSpeed2);
        var y2 = map(noise(t2), 0,1, 0, height);
        line(x, y2 + (y2 / 2), x, height); 
    }
    noStroke();
    fill(74, 47, 72);
    ellipse(px, py, bs, bs);
    fill(43, 29, 66);
    if(ox > 0){
        rect(ox, 0, 10, r);
        rect(ox, height - rx, 10, rx);
        ox -= obspeed;        
    }

    else if(ox <= 0){
        r = random(0, 200);
        rx = 300 - r;
        ox = 400;
        score++;
        count++;
        if (count % 5 === 0){
            obspeed += 1;
        }
    }
    intersect();
    fill(0);
    textSize(12);
    text("Score: " + score, 10, 10);
}

function mousePressed(){
    mySnd.play();
    yvel = 6;

}

function intersect(){
    if(py - (bs / 2) < r || py + (bs / 2) > height - rx ){
        if(px < ox + 10 & px > ox - 10){
            if(score > hscore){
                hscore = score;
                score = 0;
            }
            noLoop();
            textSize(18);
            text("You Lost :(", 300, 20);
            text("Score: " + hscore, 300, 50);
            text("Play Again!", 300, 80);
            }
        }
}

For this project, I wanted to create a game that would have a level of difficulty as time progressed. This game is a classic spinoff of the popular game flappy bird – a sphere that bounces every time you click the mouse. Your job is to make sure your sphere doesn’t hit any of the obstacles that move along the screen. In order to get the boing sound every time the ball bounces, download the zip file with all the files!

tharkare_finalzip

Alessandra Fleck – Final Project

sketch

//Name: Alessandra Fleck 
//Class Section : B
//Email: afleck@andrew.cmu.edu
//Assignment-12-Final

//USING ML5 TO IMPLEMENT MACHINE LEARNING MODEL -- see html for library src
//POSENET - HUMAN POSE ESTIMATION, USING MACHINE LEARNING  

var myCamera; //variable to hold onto webcam data
var poseNet;
var pose =[];
var imgPlanet; //store first planet image
var imgPlanet2; //store second planet image
var imgPlanet3; //store third planet image for right hip

//NON RESPONSIVE BACKGROUND ENVIRONMENT
var stars =[]; //array to hold the stars

//CHARACTER HELMET VARIABLES
var headX = 0;
var headY = 0;
//CHARACTER EYES VARIABLES
var lefteyeX = 0;
var lefteyeY = 0;
var righteyeX = 0;
var righteyeY = 0;
//CHARACTER HANDS
var lefthandX = 0;
var lefthandY = 0;
var righthandX = 0;
var righthandY = 0;
//CHARACTER HIP
var rightHipX = 0;
var rightHipY = 0;


function preload(){
    //load media for use in the sketch
    var planetOneURL = "https://i.imgur.com/f0QBerx.png";
    imgPlanet = loadImage(planetOneURL);
    var planetTwoURL = "https://i.imgur.com/v6UuYtt.png";
    imgPlanet2 = loadImage(planetTwoURL);
    var planetThreeURL = "https://i.imgur.com/bjO4uOW.png";
    imgPlanet3 = loadImage(planetThreeURL);
}

function setup(){
    createCanvas(640,480);
    //load planet one image pixels
    imgPlanet.loadPixels();

    myCamera = createCapture(VIDEO); //giving permission to browser to connect to webcam
    myCamera.size(640,480); //setting display dimensions of camera
    myCamera.hide(); // to hide extra video display below canvas
    poseNet = ml5.poseNet(myCamera, modelLoaded); // load the posenet model and connect it to the video
    poseNet.on('pose', myPose);//when person is detected, execute

}
 //check that ml5 is running on p5js 
function modelLoaded(){
    console.log('model is loaded');
}

//for one person at a time
function myPose(pose){
    //TEST POSE
    console.log(pose); //record+print the poses as detected by the camera
    //note that pose is an array
    if (pose.length > 0){
        //CHARACTER HELMET CAMERA POSITION
        headX = pose[0].pose.keypoints[0].position.x;
        headY = pose[0].pose.keypoints[0].position.y;
        
        //CHARACTER LEFT EYE CAMERA POSITION
        lefteyeX = pose[0].pose.keypoints[1].position.x;
        lefteyeY = pose[0].pose.keypoints[1].position.y;
        //CHARACTER RIGHT EYE CAMERA POSITION
        righteyeX = pose[0].pose.keypoints[2].position.x;
        righteyeY = pose[0].pose.keypoints[2].position.y;
        //CHARACTER LEFT HAND CAMERA POSITION - note that the index is for left wrist
        lefthandX = pose[0].pose.keypoints[9].position.x;
        lefthandY = pose[0].pose.keypoints[9].position.y;
        //CHARACTER RIGHT HAND CAMERA POSITION - note that the index is for left wrist

    //reduce jittering of shapes by implementing linear interpolation 
    //takes position of shape and camera position and taking 0.2 in between
         //RIGHT HAND CAMERA POSTION AND LAG USING LERP FUNCTION
        var righthandNX = pose[0].pose.keypoints[10].position.x;
        var righthandNY = pose[0].pose.keypoints[10].position.y;
        righthandX = lerp(righthandX,righthandNX,0.8);
        righthandY = lerp(righthandY,righthandNY,0.8);

        //CHARACTER RIGHT HIP CAMERA POSITION
        rightHipX = pose[0].pose.keypoints[12].position.x;
        rightHipY = pose[0].pose.keypoints[12].position.y;

    }
}

function draw(){
    //draw the camera image to the canvas using image function
    image(myCamera, 0, 0, width, height); 

    //stars at random
    for(var i=0; i<random(8); i++){
        stars.push(new star()); //put new star into array
    }

    for (var birth of stars){
        birth.display();
    }

    //maintain shape scale to distance from camera
    var cameraDistance = dist(lefteyeX, lefteyeY, righteyeX, righteyeY); 

    filter(POSTERIZE,8); // filters video image into posterize
    filter(INVERT); //overlay gray filter

   
    //CHARACTER HEAD SHAPE SETTING
    fill(250);
    ellipse(headX,headY,200,200); //using nose location for character head
    fill(0);
    ellipse(headX,headY+25,30,10); //using nose location for character mouth
    
    //CHARACTER LEFT EYE SHAPE SETTING
    fill(0);
    ellipse(lefteyeX, lefteyeY, cameraDistance/2,cameraDistance/2);
    //CHARACTER RIGHT EYE SHAPE SETTING
    fill(0);
    ellipse(righteyeX, righteyeY, cameraDistance/2,cameraDistance/2);

    //FIRST (GREEN) PLANET IMAGE MOVING IN RESPONSE TO RIGHT HAND
    image(imgPlanet,righthandX,righthandY,50,50);
    image(imgPlanet,righthandX+50,righthandY+50,100,100);
    image(imgPlanet,righthandX+20,righthandY+100,10,10);
    //SECOND (ORANGE) PLANET IMAGE MOVING IN RESPONSE TO LEFT HAND
    image(imgPlanet2,lefthandX+20,lefthandY,50,50);
    image(imgPlanet2,lefthandX-100,lefthandY,30,30);
    image(imgPlanet2,lefthandX+50,lefthandY+50,60,60);

    //USING CHARACTER RIGHT HIP AS GALAXY
    image(imgPlanet3,rightHipX,rightHipY-50,300,150);


}

function star(){
    this.posX = 0;
    this.posY = random(-100,400);
    this.size = random(50,100);
    this.display = function(){
        fill(0);
        ellipse(this.posX,this.posY, this.size);
    }
}




index

afleck_Final

 

For the final project I wanted to explore a part of p5js that involved computer vision. Originally going to do an Augmented Reality project for objects placement, I ended up going more towards computer vision as it is easier to do with a webcam and there are lots of resources available for it in correlation with p5js. To use computer vision I added the Ml5 library to my html file and used the posNet() model that predicts live time human body estimation with machine learning.

Using posNet I was able to identify different keypoint indexes for different parts of the body and link those to where I could input shapes. As I love space, I thought it might be neat to create a responsive space environment with the movement of the body. I began with making the head and eyes as a large moon thats responds to different distances from the camera and scales to the distance. I then created planets in illustrator and added them into the scene. Using linear interpolation, I was able to detach the keypoint of the wrists from the body and create a bit of a lag so that the planets had the effects of following the wrists, where in reality they were being offset from the keypoint of the wrist and the coordinates of the object.

From this project I got to explore this form of machine learning for the first time. Though it was not as refined as I wanted it to be (as much of the information was very new to me), I enjoyed looking at how computer vision operates and the things it can can do with augmenting reality.

Note: the camera will not work as the library needs to be linked with the html, download and open the source code in the zip file and just open the html file to get started!

 

cmhoward-finalproject

For my project, I created an animated children’s book. This project was really exciting to create as I was able to practice using simple and more complex animation. With having 10 pages, I focused on experimenting with different kinds of animations and page turning effects. All of the backgrounds were drawn by me! The animated objects were also drawn by me, or created in p5.js. For the sake of cleanliness and consistency, I decided that drawing the background images myself would be the best possible solution.

The code is structured by creating an array of functions that implements the functions by indexing through a page number counter.

Detailed page explanations below:

On page 4, the Giraffe suggests for the Lion to sleep with a spoon under his pillow to make it rain, so the user must move the spoon to the pillow. When the spoon is within the boundaries of the pillow, it flips to the next page. 

On page 5, I chose to do a simple page turning animation where the user must click within the boundary of the page turning image. While not nearly as complex as other pages, it was necessary to add this page for the sake of the story!

On page 9, the animals are having a party so I created an object animation of balloons floating to the top of the page. When the array length (i.e # of balloons) reaches 10 balloons, it moves to the next page.

On the last page, the animals begin to dance and I use a frame animation to flip through images of the animals moving. It also begins to rain and I created an object animation of rain falling from the top of the canvas.

Since I created a lot of my own images, I decided to package this project on my computer and run it on a local server.

To run this program:

  1. Download .zip file and extract it to your computer
  2. Open a command prompt, and type cd “path to file” (ex: C:\Users\Cassie Howard\Downloads\cmhoward-final-project\template-all)
  3. Then connect to python “python -m http.server”
  4. After it connects, open up http://localhost:8000 in your web browser.

If you get confused on how to move to the next page, remember the different page turning implementations i.e clicking on the jittering objects, completing the animation, or simply waiting (i.e for ten balloons to appear).

cmhoward-final-project

Code to drag objects inspired by:

Draggable Example (written by Daniel Shiffman)

code below! (it’s not NOT working, you just can’t see all of the background images until you connect to a local server!)

sketch-87

//Cassandra Howard
//Section B
//cmhoward@andrew.cmu.edu
//Final Project

//IMAGE VARIABLES
var page1;
var page2;
var page3;
var page4;
var spoon;
var page5;
var page6;
var page7;
var page8;
var page9;
var page10;
var turn_page;
var tomato;

//PAGE COUNTER
var page = 0;

//LOOP THROUGH PAGES
var clickFunctions = [click1, click2, click3, click4, click5, click6, click7, click8, click9, click10];
var drawFunctions = [draw1, draw2, draw3, draw4, draw5, draw6, draw7, draw8, draw9, draw10];

//DRAW1 GLOBAL VARIABLES
//VERTICES POINTS OF SUN
var sunX = [40, 50, 60, 50, 80, 50, 60, 50, 40, 50, 20, 50, 40];
var sunY = [26.5, 53, 80, 53, 53, 53, 26.5, 53, 80, 53, 53, 53, 26.5];

//DRAW2 GLOBAL VARIABLES
//SET Y VALUE OF TOMATOES, INTIALIZE TOMATOES POSITIONS 
var tomatoY1 = 315;
var tomatoY2 = 300;
var tomatoFalling = false;

//DRAW4 GLOBAL VARIABLES
//INTIALIZE SPOON VALUES
var draggingSpoon = false;
var rolloverSpoon = false;
var spoonX;
var spoonY;
var spoonW;
var spoonH;
var offsetSpoonX; 
var offsetSpoonY;

//DRAW6 GLOBAL VARIABLES
//LOAD IMAGE FILES FOR FRAME ANIMATION, CREATE EMPTY ARRAY FOR IMAGES
//INTIALIZE COIN POSITION
var frames = [];
var filenames = [
    "assets/coin_1.png",
    "assets/coin_2.png",
    "assets/coin_3.png",
    "assets/coin_4.png"
    ];
var coinX = 50;
var coinY = 50;
var targetX;
var targetY;
var dx;
var dy;
var distanceFromCoinToTarget;

//DRAW7 GLOBAL VARIABLES
//INTIALIZE APPLE VALUES
var draggingApple = false;
var rolloverApple = false;
var appleX;
var appleY;
var appleW;
var appleH;
var offsetAppleX;
var offsetAppleY;

//DRAW8 GLOBAL VARIABLES
//INTIALIZE APPLE2 VALUES
var draggingApple2 = false;
var rolloverApple2 = false;
var apple2X;
var apple2Y;
var apple2W;
var apple2H;
var offsetApple2X;
var offsetApple2Y;

//DRAW9 GLOBAL VARIABLES
//CREATE EMMPTY ARRAY FOR BALLOONS
var balloons = [];
var bx;
var b; 
var by;


//DRAW10 GLOBAL VARIABLES
//LOAD IMAGES FOR FRAME ANIMATION, CREATE EMPTY ARRAY FOR IMAGES
//CREATE EMPTY ARRAY FOR RAINDROPS
var frames2 = [];
var filenames2 = [
    "assets/dance_1.png",
    "assets/dance_2.png",
    ];
var raindrops = []; 
var rx; 
var ry;


//LOAD BACKGROUND IMAGES FOR EACH PAGE
function setup() {
    createCanvas(480, 480);
    page1 = loadImage("assets/page_1.jpg");
    page2 = loadImage("assets/page_2.jpg");
    tomato = loadImage("assets/tomato.png");
    page3 = loadImage("assets/page_3.jpg");
    turn_page = loadImage("assets/turn_page.png");
    page4 = loadImage("assets/page_4.jpg");
    spoon = loadImage("assets/spoon.png");
    spoonX = 100;
    spoonY = 200;
    spoonW = 50;
    spoonH = 50;
    page5 = loadImage("assets/page_5.jpg");
    page6 = loadImage("assets/page_6.jpg");
    //PUSH IMAGES INTO EMPTY ARRAY
    for (var i = 0; i < filenames.length; i++) {
        frames.push(loadImage(filenames[i]));
    }
    //SET ANIMATION VARIABLES
    coinX = width / 2;
    coinY = height / 2;
    targetX = coinX;
    targetY = coinY;
    page7 = loadImage("assets/page_7.jpg");
    apple = loadImage('assets/apple.png');
    //SET APPLE POSITION
    appleX = 240;
    appleY = 355;
    appleW = 50;
    appleH = 50;
    page8 = loadImage("assets/page_8.jpg");
    //SET APPLE2 POSITION
    apple2X = 100;
    apple2Y = 355;
    apple2W = 50;
    apple2H = 50;
    page9 = loadImage("assets/page_9.jpg");
    //CREATE BALLOON OBJECTS
    for (var i = 0; i < 5; i++) {
        var bx = random(0, width);
        var b = random(50, 80);
        var by = height;
        balloons[i] = makeBalloon(bx, by, b);
    }
    page10 = loadImage("assets/page_10.jpg");
    //PUSH IMAGES INTO EMPTY ARRAY
    for (var i = 0; i < filenames2.length; i++) {
        frames2.push(loadImage(filenames2[i]))
    }
    //CREATE RAINDROP OBJECTS
    for (var i = 0; i < 5; i++) {
        var rx = random(0, width);
        var ry = 0;
        raindrops[i] = makeRaindrop(rx, ry);
    }
    frameRate(5);
}

//CLICK THROUGH PAGES WITH CLICK FUNCTIONS
function mouseClicked() {
    clickFunctions[page]();
}

//CALL PAGE FUNCTIONS
function draw() {
    drawFunctions[page]();
}

//OBJECT DRAGGING FUNCTIONS
function mousePressed() {
    //PAGE 4
    if (mouseX > spoonX & mouseX < spoonX + spoonW && mouseY > spoonY && mouseY < spoonY + spoonH) {
        draggingSpoon = true;
        offsetSpoonX = spoonX - mouseX;
        offsetSpoonY = spoonY - mouseY;
    }

    //PAGE 6 
    if (mouseX > appleX & mouseX < appleX + appleW && mouseY > appleY && mouseY < appleY + appleH) {
        draggingApple = true;
        offsetAppleX = appleX - mouseX;
        offsetAppleY = appleY - mouseY;
    }

    //PAGE 7
    if (mouseX > apple2X & mouseX < apple2X + apple2W && mouseY > apple2Y && mouseY < apple2Y + apple2H) {
        draggingApple2 = true;
        offsetApple2X = apple2X - mouseX;
        offsetApple2Y = apple2Y - mouseY;
    }       
}

//PAGE 1
//MAKE SUN JITTER, CLICK SUN TO MOVE TO NEXT PAGE
function draw1() {
    noStroke();
    background('white');
    image(page1, 0, 0, page1.width, page1.height);
    var sunPoints = sunX.length;
    fill(254, 192, 68);
    beginShape();
    for (var i = 0; i < sunPoints; i++) {
        var sunpX = sunX[i] + random(-2, 2);
        var sunpY = sunY[i] + random(-2, 2);
        vertex(sunpX, sunpY); 
    }
    endShape(CLOSE);
    ellipse(50, 53, 10, 10);
}

function click1() {
    if (mouseX < 60 & mouseX > 40 && mouseY < 60 && mouseY > 40) {
        page = 1;
    };
}


//PAGE 2
//MAKE TOMATOES JITTER, CLICK TOMATOES TO MOVE TO NEXT PAGE
function draw2() {
    noStroke();
    background('white');
    image(page2, 0, 0, page2.width, page2.height);
    if (tomatoFalling === true) {
        tomatoY1 += 10;
        tomatoY2 += 10;
    } else {
        tomatoY1 = random(350, 355);
        tomatoY2 = random(300, 305);
    }

    image(tomato, random(260, 265), tomatoY1, 30, 30);
    image(tomato, random(270, 275), tomatoY2, 30, 30);
    image(tomato, random(315, 320), tomatoY1, 30, 30);
    image(tomato, random(310, 315), tomatoY2, 30, 30);
    image(tomato, random(360, 365), tomatoY1, 30, 30);
    image(tomato, random(355, 360), tomatoY2, 30, 30);

    if (tomatoY1 > page2.height & tomatoY2 > page2.height) {
        page = 2;
    }
}

function click2() {
    if (mouseX < 365 & mouseX > 260 && mouseY > 300 && mouseY < 355) {
        tomatoFalling = true;
    }
}

//PAGE 3
//LOAD BACKGROUND IMAGE, CLICK PAGE TURN ANIMATION TO GO TO NEXT PAGE
function draw3() {
    noStroke();
    background('white');
    image(page3, 0, 0, page3.width, page3.height);
    image(turn_page, 430, 430, turn_page.width, turn_page.height);
}

function click3() {
    if (mouseX < 480 & mouseX > 400 && mouseY < 480 && mouseY > 400) {
        page = 3;
    }
}

//PAGE 4
//COMPLETE DRAGGING SPOON TO MOVE TO NEXT PAGE
function draw4() {
    noStroke();
    background('white');
    image(page4, 0, 0, page4.width, page4.height);

    if (mouseX > spoonX & mouseX < spoonX + spoonW && mouseY > spoonY && mouseY < spoonY + spoonH) {
        rolloverSpoon = true;
    }
    else {
        rolloverSpoon = false;
    }

    if (draggingSpoon) {
        spoonX = mouseX + offsetSpoonX;
        spoonY = mouseY + offsetSpoonY;
    }

    image(spoon, spoonX, spoonY, spoonW, spoonH);

    if (spoonX > 100 & spoonX < 200 && spoonY > 50 && spoonY < 100) {
        page = 4;
    }
}

function mouseReleased() {
    dragging = false;
}

function click4() {

}


//PAGE 5
//LOAD BACKGROUND IMAGE, CLICK PAGE TURN ANIMATION TO FLIP TO NEXT PAGE
function draw5() {
    noStroke();
    background('white');
    image(page5, 0, 0, page5.width, page5.height);
    image(turn_page, 430, 430, turn_page.width, turn_page.height);
}

function click5() {
    if (mouseX < 480 & mouseX > 400 && mouseY < 480 && mouseY > 400) {
        page = 5;
    }
}

//PAGE 6
//TOSS COIN INTO POND, USING FRAME ANIMATION, WHEN COIN REACHES POND, FLIP TO NEXT PAGE
function draw6() {
    noStroke();
    background('white');
    image(page6, 0, 0, page6.width, page6.height);

    dx = targetX - coinX;
    dy = targetY - coinY;
    distanceFromCoinToTarget = sqrt(dx*dx + dy*dy);

    coinX = lerp(coinX, targetX, 0.1);
    coinY = lerp(coinX, targetY, 0.1);

    if (targetX < coinX) {
        push();
        scale(-1, 1);
        image(frames[frameCount % frames.length], -coinX, coinY);
        pop();
    }
    else {
        image(frames[frameCount % frames.length], coinX, coinY);
    }

    if (coinY > 350) {
        page = 6;
    }
}

function click6() {
    targetX = mouseX;
    targetY = mouseY;
}

//PAGE 7
//DRAG APPLE TO LION, WHEN APPLE REACHES LION, FLIP TO NEXT PAGE
function draw7() {
    noStroke();
    background('white');
    image(page7, 0, 0, page7.width, page7.height);

    if (mouseX > appleX & mouseX < appleX + appleW && appleY > appleY && mouseY < appleY + appleH) {
        rolloverApple = true;
    }
    else {
        rolloverApple = false;
    }

    if (draggingApple) {
        appleX = mouseX + offsetAppleX;
        appleY = mouseY + offsetAppleY;
    }

    image(apple, appleX, appleY, appleW, appleH);

    if (appleX > 75 & appleX < 125 && appleY > 300 && appleY < 350) {
        page = 7;
    }
}

function click7() {

}

//PAGE 8
//DRAG APPLE FROM LION TO OWL, WHEN APPLE REACHES OWL, FLIP TO NEXT PAGE
function draw8() {
    noStroke();
    background('white');
    image(page8, 0, 0, page8.width, page8.height);

    if (mouseX > apple2X & mouseX < apple2X + apple2W && apple2Y > apple2Y && mouseY < apple2Y + apple2H) {
    rolloverApple2 = true;
    }
    else {
        rolloverApple2 = false;
    }

    if (draggingApple2) {
        apple2X = mouseX + offsetApple2X;
        apple2Y = mouseY + offsetApple2Y;
    }

    image(apple, apple2X, apple2Y, apple2W, apple2H);

    if (apple2X > 230 & apple2X < 300 && apple2Y > 150 && apple2Y < 200) {
        page = 8;
    }
}

function click8() {

}

//PAGE 9
//CREATE BALLOONS THAT RISE FROM THE BOTTOM OF THE SCREEN, WHEN 10 BALLOONS HAVE BEEN CREATED, MOVE TO NEXT PAGE
function draw9() {
    background('white');
    image(page9, 0, 0, page9.width, page9.height);

    updateAndDisplayBalloons();
    addNewBalloons();

    if (balloons.length > 10) {
        page = 9;
    }
}

function updateAndDisplayBalloons() {
    for (var i = 0; i < balloons.length; i++) {
        balloons[i].move();
        balloons[i].display();
    }
}

function addNewBalloons() {
    var newBalloonProb = .05;
    var b = random(50, 80);
    if (random(0, 1) < newBalloonProb) {
        balloons.push(makeBalloon(random(0, width), height, random(50, 80)));
    }
}

function balloonMove() {
    this.y -= this.speed;
}

function balloonDisplay(){
    push();
    if (this.typeColor < 1) {
        fill(255, 0, 0, 100);
    }
    if (this.typeColor > 1 & this.typeColor < 2) {
        fill(0, 0, 255, 100);
    }
    if (this.typeColor > 2 & this.typeColor < 3) {
        fill(128, 0, 128, 100);
    }
    ellipse(this.x, this.y, this.breadth/1.5, this.breadth);
    stroke('black');
    strokeWeight(1);
    line(this.x, this.y + this.breadth/2, this.x, this.y + 100);
    
    pop();
}

function makeBalloon(bx, by, b) {
    var balloons = {x: bx, y: by, move: balloonMove, display: balloonDisplay, speed: 5, breadth: random(50, 80), place: random(50, 250), type: int(random(0, 3)), typeColor: random(0, 3)}
    return balloons;
}

function click9() {

}

//PAGE 10
//CREATE RAINDROPS FALLING FROM TOP OF CANVAS
//USE FRAME ANIMATION TO MAKE ANIMALS DANCE 
function draw10() {
    background('white')
    image(page10, 0, 0, page10.width, page10.height);

    image(frames2[frameCount % frames2.length], 0, 180);

    updateAndDisplayRaindrops();
    addNewRaindrops();
}

function updateAndDisplayRaindrops() {
    for (var i = 0; i < raindrops.length; i++) {
        raindrops[i].move();
        raindrops[i].display();
    }
}

function addNewRaindrops() {
    var newRaindropProb = .25;
    if (random(0, 1) < newRaindropProb) {
        raindrops.push(makeRaindrop(random(0, width), 0));
    }
}

function raindropsMove() {
    this.y += this.speed;
}

function raindropsDisplay(){
    push();
    fill(135, 206, 250, 100);
    beginShape();
    curveVertex(this.x, this.y);
    curveVertex(this.x-5, this.y+15);
    curveVertex(this.x, this.y+20);
    curveVertex(this.x+5, this.y+15);
    curveVertex(this.x, this.y);
    endShape(CLOSE);
    pop();
}

function makeRaindrop(rx, ry) {
    var raindrops = {x: rx, y: ry, move: raindropsMove, display: raindropsDisplay, speed: 5, place: random(50, 250)}
    return raindrops;
}

function click10() {

}

//END

Jisoo Geum Final Project

 

jgeum-final project

I am uploading a zip file instead of the sketch file since the program contains sound.

My final project is an educational program that teaches the user to learn (hopefully) about the Korean alphabet: Hangul. Hangul is very easy to learn because it does not require people to memorize the meaning of each character. Since Hangul is an alphabet system like English, anyone can read without knowing the meaning itself. I only focused on the Consonant letters of Hangul so the alphabets showing up on the program does not make a full word or a letter.

As I was writing the program, I realized how complicated it is to teach a language even though I initially thought Hangul was relatively simple. Thus, I am planning to expand on this project and hopefully make a program that covers not only consonants but also vowels and maybe some simple words.

(My original plan was to make the user draw on top of the text using turtle graphics, but somehow the code didn’t work. I canceled out the turtle graphics part. )

Final Project-Urban Wildlife-Veronica Wang

In this interactive game/animation:
(click on the canvas first)
Press left arrow to add birds, press right arrow to add chimneys. Bird nests and raccoons will show up according to the added elements. The position of mouseY changes the color of the sky. As more birds are added, bird sound gets louder.

sketch

//Veronica Wang
//Section B
//yiruiw@andrew.cmu.edu
//Final Project

var Y_AXIS = 1; //gradient sky axis
var c1, c2; //gradient sky colors
var PREFIX = "https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/";
//var PREFIX = "";
var birdSound;
var trainSound;
var bV = 0.2;
var houseList = []; //array of houses
var allTrees = []; //trees
var birdList = []; //birds
var raccoonList = []; //raccoons
var flap = true;
var nestCount = 0;
var birdperNest = 3; //for every three birds draw a nest
var trainList = []; //trains
var rachouseCount = 0;

frameCount = 200;


function preload(){
    birdSound = loadSound(PREFIX + "birds.wav");
    trainSound = loadSound(PREFIX + "train.wav");
    trainSound.setVolume(0.5);
}

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

    //sky colors
    c1 = color(244, 248, 255); //light blue
    c2 = color(94, 164, 186); //dark teal blue

    drawBackground();

    //draw houses
    for(var i = 0; i < 10; i++) {
        var newX = random(80, 420);
        var newY = random(120, 200);
        if (houseList.length < 1){
            houseList.push(makeHouse(newX, newY));
        } 
        else{
            while (checkifLess(newX, newY, houseList, 30)){
                newX = random(80, 420);
                newY = random(120, 200);
            }
            houseList.push(makeHouse(newX, newY));
        }
    }

    //draw trees
    for(var i = 0; i < 40; i++) {
        allTrees.push(makeTree());
    }
    sortTree(allTrees);
    sortTree(houseList);

    //draw creatures
    birdList.push(makeBird(width / 2,height / 2, 15));
    raccoonList.push(makeRac(width / 2, height / 2, 5));


}

function draw() {
    //play sound
    birdSound.setVolume(bV);
    if (frameCount % 100 == 0){
        birdSound.play();
    }
    //set volume to be proportional to number of birds
    bV = (map(birdList.length, 0, 20, 0, 1));
    

    drawBackground();
    drawStairs();

    //initial number of artificial nests
    nestCount = 0;
    rachouseCount = 0;

    //raccoon house counter
    for (var i = 0; i < houseList.length; i++) {
        if (houseList[i].rh){
            rachouseCount += 1;
        }   
    }

    //add raccoons
    if (raccoonList.length < rachouseCount * 2){
        raccoonList.push(makeRac(random(0, 500), random(150, 220)));
    }

    //drawing raccoons and removing them from array if out of canvas
    for (var i = 0; i < raccoonList.length; i++) {
        raccoonList[i].draw();
        raccoonList[i].rx += raccoonList[i].vel;
        if (racoutofBound(raccoonList[i])){
            raccoonList.splice(i, 1);
            i -= 1;
        }       
    }

    //draw houses
    for (var i = 0; i < houseList.length; i++) {
        houseList[i].draw();     
    }

    //draw trees
    for (var i = 0; i < allTrees.length; i++){
        if (i % 3 == 0){
            allTrees[i].draw1();
        } else if (i % 3 == 1){
            allTrees[i].draw2();
        } else {
            allTrees[i].draw3();
        }
        if (allTrees[i].nest){
            nestCount += 1;
        }
    }

    drawTracks();
    
    //bird wing flap
    if (frameCount % 40 == 0){
        flap = !(flap);
    }

    //if bird is out of canvas, take it out of the array
    for (var i = 0; i < birdList.length; i++) {
        if (birdoutofBound(birdList[i])){
            birdList.splice(i, 1);
            i -= 1;
        }
    }

    //draw birds
    for (var i = 0; i < birdList.length; i++) {
        if (flap){
            birdList[i].draw2();
        } else {
            birdList[i].draw();
        }
        birdList[i].bx += birdList[i].xvel * noise(1);
        birdList[i].by += birdList[i].yvel * noise(1);
    };

    //adding random movement and scale birds
    if (frameCount % 100 == 0){
        for (var i = 0; i < birdList.length; i++) {
            birdList[i].xvel += random(-3, 3) * (map(pow(2, birdList[i].by / 50), 0, pow(2, 300 / 50), 1, 100)) / 35;
            birdList[i].yvel += random(-1, 1) * (map(pow(2, birdList[i].by / 50), 0, pow(2, 300 / 50), 1, 100)) / 35;

        }
    }
    

    //night sky filter
    var darkness = map(mouseY, 0, height, 0, 200);
    fill(0, 0, 0, darkness);
    noStroke();
    rect(0, 0, width, height);

    //add nest to empty trees
    if (birdList.length > 0 & int(birdList.length / birdperNest) < 40){
        if (int(birdList.length / birdperNest) > nestCount){
            var seltree = int(random(0, allTrees.length));
            while (allTrees[seltree].nest){
                seltree = int(random(0, allTrees.length));
            }
            allTrees[seltree].nest = true;
        } else if (int(birdList.length / birdperNest) < nestCount){
            var seltree = int(random(0, allTrees.length));
            if (allTrees[seltree].nest == true){
                allTrees[seltree].nest = false;
            }
            
        }
    }

    //draw train
    if (frameCount % 400 == 0) {
        trainList.push(makeTrain());
        trainSound.play();
    }
    for (var i = 0; i < trainList.length; i++) {
        trainList[i].x -= trainList[i].vel;
        trainList[i].draw();
    };
    if (trainList.length > 0){
        if (trainList[0].x < -750){
            trainList.splice(0, 1);
        }
    }
}

//if raccoon is out of canvas
function racoutofBound(bird){
    if (bird.rx < 0){
        return true;
    } else if (bird.rx > width){
        return true;
    } else if (bird.ry < 0){
        return true;
    } else if (bird.ry > height){
        return true;
    }
    return false;
}

//if bird is out of canvas
function birdoutofBound(bird){
    if (bird.bx < 0){
        return true;
    } else if (bird.bx > width){
        return true;
    } else if (bird.by < 0){
        return true;
    } else if (bird.by > height){
        return true;
    }
    return false;
}

//sort tree order by y position
function sortTree(treelist){
    n = treelist.length;
    for (var i = 0; i < n; i++){
        for (var j = 0; j < n - i - 1; j++){
            
            if (treelist[j].y > treelist[j+1].y){
                var temp = treelist[j];
                treelist[j] = treelist[j+1];
                treelist[j+1] = temp;
            }
        }
    }
}

//draw tree outside of houses
function ispointIn(x, y, house){

    var x1 = house.x;
    var x2 = house.x + house.w;
    var y1 = house.y - house.w / 3;
    var y2 = house.y + house.h * house.f;
    if (x < x1){
        return false;
    } else if (x > x2){
        return false;
    } else if (y < y1){
        return false;
    } else if (y > y2 + 13){
        return false;
    }
    return true;
}

//goes through list to check if point is outside the boundary
function hListcheck(x, y, list, n){
    if (list.length < 1){
        return false;
    }
    if (n < list.length - 2){
        return (ispointIn(x, y, list[n]) || hListcheck(x, y, list, n + 1));
    } else {
        return ispointIn(x, y, list[n]);
    }
}

//make sure houses are not overlapping
function checkifLess(x, y, list, mindist){
    var chck = false;
    for (var i = 0; i < list.length; i++) {
        var objdist = dist(x, y, list[i].x, list[i].y);
        if (objdist < mindist){
            chck = true;
        }
    }
    return chck;
}

//house object
function makeHouse(locX, locY){
    var num = 75;
    var house = { x: locX,
                  y: locY,
                  w: map(pow(2, locY / num), 0, pow(2, 300 / num), 1, 100),  //proportionally scale house in the distance
                  f: floor(random() * 2 + 1), //random number of floors from 1-3
                  rh: false, //raccoon houses
                  draw: drawHouse
                };
    return house;
}

function drawHouse(){
    noStroke();
    fill(173, 110, 110);
    var h = this.w / 2;
    rect(this.x, this.y, this.w, h * this.f); //body of house
    rect(this.x + this.w * 0.7, this.y - this.w / 3, 
        this.w / 5, this.w / 3); //chimney
    triangle(this.x, this.y, 
            this.x + this.w / 2, this.y - this.w / 3, 
            this.x + this.w, this.y); //roof
    if(this.f == 1){
        //gradient
        for (var i = 0; i < this.y / 10; i++) { 
            var op2 = map(i, 0, 50, 0, 200);
            stroke(201, 141, 141, op2); 
            line(this.x, i * this.y * 0.005 + this.y, 
                this.x + this.w, i * this.y * 0.005 + this.y);
        }
        drawWindow(this.x + this.w / 5, this.y + this.w / 6, 
                this.w * 0.3, this.w / 5);
        drawShrub(this.x, this.y + h, 
                this.w * 0.5, this.w * 0.3);

    }else{
        //gradient
        for (var i = 0; i < this.y / 5; i++) { 
            var op3 = map(i, 0, 50, 0, 200);
            stroke(201, 141, 141, op3); 
            line(this.x, i * this.y * 0.005 + this.y, 
                this.x + this.w, i * this.y * 0.005 + this.y);
        }
        drawWindow(this.x + this.w / 5, this.y + this.w / 6, 
                this.w * 0.3, this.w / 5);
        drawWindow(this.x + this.w / 5, this.y + this.w * 0.6, 
                this.w * 0.3, this.w / 5);
        drawShrub(this.x, this.y + this.w, 
                this.w * 0.4, this.w * 0.3);
    } 

    if(this.rh){
        fill(135, 81, 132);
        rect(this.x + this.w, 
             this.y + h / 5, this.w / 6, (h * this.f) * 0.75);
        triangle(this.x + this.w, this.y + h * this.f, 
                 this.x + this.w, this.y + (h * this.f) / 2, 
                 this.x + this.w + this.w / 3, this.y + h * this.f);
    }
}

function drawWindow(x, y, w, h){
    noStroke();
    fill(239, 233, 218);
    rect(x, y, w, h);
}

function drawShrub(x, y, w, h){
    noStroke();
    fill(143, 168, 104);
    ellipse(x, y, w, h);
    ellipse(x + 5, y, w * 0.8, h * 0.5);
    ellipse(x + 3, y - 2, w * 0.8, h * 0.8);

}

function makeTree(){
    var num1 = 75;

    var tempY = random(120, 200);
    var tempX = random(0, 450)
    var mult = map(pow(2, tempY / num1), 0, pow(2, 300 / num1), 1, 100) / 40;

    var tX = tempX + 3 * mult;
    var tY = tempY + 30 * mult;

    while (hListcheck(tX, tY, houseList, 0)){
        tempY = random(120, 200);
        tempX = random(0, 450)
        tX = tempX + 3 * mult;
        tY = tempY + 30 * mult;
    }
    
    var tree = { x: tempX,
                 y: tempY,
                 w: map(pow(2, tempY / num1), 0, pow(2, 300 / num1), 1, 100),  //proportionally scale house in the distance
                 m: map(pow(2, tempY / num1), 0, pow(2, 300 / num1), 1, 100) / 40,
                 draw1: tree1draw,
                 draw2: tree2draw,
                 draw3: tree3draw,
                 nest: false
                };
    return tree;

}


function tree1draw(){
    noStroke();
    push();
    
    translate(this.x, this.y);
    scale(this.m, this.m);
    fill(122, 98, 66);
    rect(3, 0, 3, 30);
    fill(95, 140, 99, 180);
    ellipse(0, -5, 30, 35);
    ellipse(15, -5, 20, 25);
    ellipse(5, 8, 50, 20);
    if(this.nest == true){
        fill(89, 68, 49);
        rect(0, 0, 10, 10);
        fill(193, 164, 137);
        ellipse(5, 5, 4, 4);
    }
    pop();
}

function tree2draw(){
    
    noStroke();
    push();
    translate(this.x, this.y);
    scale(this.m, this.m);
    fill(122, 98, 66);
    rect(5, 0, 3, 30);
    fill(95, 120, 96, 200);
    triangle(18, 18, -6, 18, 6, -30);
    if(this.nest == true){
        fill(89, 68, 49);
        rect(0, 0, 10, 10);
        fill(193, 164, 137);
        ellipse(5, 5, 4, 4);
    }
    pop();

}

function tree3draw(){
    noStroke();
    push();
    var mult = this.w / 40;
    translate(this.x, this.y);
    scale(mult, mult);
    fill(122, 98, 66);
    rect(3, 0, 3, 30);
    fill(108, 132, 102, 200);
    ellipse(4, -17, 20, 20);
    ellipse(4, -8, 30, 20);
    ellipse(4, 5, 40, 25);
    if(this.nest == true){
        fill(89, 68, 49);
        rect(0, 0, 10, 10);
        fill(193, 164, 137);
        ellipse(5, 5, 4, 4);
    }
    pop();

}

function drawBackground(){

    //draw background gradient
    setGradient(0, 0, width, height * 0.45, c1, c2, Y_AXIS);

    //mountain layer 1
    noStroke();
    fill(75, 137, 138);
    beginShape();
    curveVertex(0, height);
    curveVertex(0, height);
    curveVertex(0, 200);
    curveVertex(0, 180);
    curveVertex(190, 60);
    curveVertex(280, 80);
    curveVertex(350, 70);
    curveVertex(420, 100);
    curveVertex(520, 80);
    curveVertex(width, height);
    curveVertex(width, height);
    endShape();
    
    //gradient mask
    for (var i = 0; i < 500; i++) { 
        var op = map(i, 100, 500, 0, 255);
        stroke(255, 255, 255, op); 
        line(0, i * 0.6, width, i * 0.6);
    }

    //mountain layer 2
    noStroke();
    strokeWeight(1);
    fill(75, 147, 154);
    beginShape();
    curveVertex(0, height);
    curveVertex(0, height);
    curveVertex(0, 120);
    curveVertex(0, 110);
    curveVertex(100, 70);
    curveVertex(200, 130);
    curveVertex(300, 90);
    curveVertex(400, 130);
    curveVertex(500, 120);
    curveVertex(500, 130);
    curveVertex(width, height);
    curveVertex(width, height);
    endShape();

    //gradient mask
    for (var i = 0; i < 500; i++) { 
        var op = map(i, 100, 500, 0, 255);
        stroke(255, 183, 80, op); 
        line(0, i, width, i);
    }

}

function drawStairs(){
    noStroke();
    fill(99, 88, 77);
    for (var i = 0; i < 15; i++) {
        rect(i * 5 + 30, i * 3 + 190, 8, 1.5);
        rect(i * 5 + 40, -i * 2 + 190, 8, 1);
        rect(i * 5 + 30, i * 3 + 120, 1 + i * 0.5, 1)
    };

    rect(35, 190, 2, 45);
    rect(28, 190, 2, 45);
    rect(28, 210, 8, 2);

    rect(110, 162, 1, 35);
    rect(116, 162, 1, 35);
    rect(110, 170, 6, 1);

    strokeWeight(2);
    line(1, 1, 100, 100);

    for (var j = 0; j < 30; j++) {
        fill(117, 107, 98);
        rect(j * 2 + 440, j * 3 + 130, 1 + j * 0.7, 1);
    };

}

function drawTracks(){
    stroke(122, 102, 82);
    strokeWeight(2);
    line(0, 280, 500, 280);
    strokeWeight(1);
    line(0, 275, 500, 275);

    for (var i = 0; i < 15; i++) {
        rect(i * 40, 273, 1, 6);
    };
}

function makeTrain(){
    var train = { x: 500,
                  y: 277,
                  vel: random(5, 15),
                  draw: drawTrain
                };
    return train;
}

function drawTrain(){
    noStroke();
    fill(80);
    triangle(this.x, this.y - 5, this.x + 25, this.y - 5, this.x + 25, this.y - 20);
    rect(this.x + 12, this.y - 40, 10, 15);
    rect(this.x + 20, this.y - 40, 50, 35);
    rect(this.x + 22, this.y - 50, 15, 25);
    rect(this.x + 55, this.y - 59, 30, 4);
    rect(this.x + 70, this.y - 16, 16, 8);
    rect(this.x + 80, this.y - 16, 8, 8);
    rect(this.x + 88, this.y - 13, 18, 3);
    fill(140, 89, 88);
    rect(this.x + 16, this.y - 45, 40, 25);
    fill(140, 100, 88);
    rect(this.x + 60, this.y - 55, 20, 45);
    fill(201, 216, 215);
    rect(this.x + 64, this.y - 52, 12, 18);
    fill(96, 83, 58);
    ellipse(this.x + 30, this.y - 5, 15, 15);
    ellipse(this.x + 70, this.y - 5, 15, 15);

    for (var i = 1; i < 5; i++) {
        fill(80);
        rect(this.x + 100 * i, this.y - 55, 90, 3);
        rect(this.x + 100 * i, this.y - 13, 100, 3);
        fill(140, 120, 88);
        rect(this.x + 5 + 100 * i, this.y - 52, 80, 45);
        fill(140, 130, 98);
        rect(this.x + 5 + 100 * i, this.y - 22, 80, 15);
        fill(201, 216, 215);
        rect(this.x + 12 + 100 * i, this.y - 48, 30, 18);
        rect(this.x + 48 + 100 * i, this.y - 48, 30, 18);
        fill(96, 83, 58);
        ellipse(this.x + 20 + 100 * i, this.y - 5, 15, 15);
        ellipse(this.x + 70 + 100 * i, this.y - 5, 15, 15);
    };

    fill(0);
    drawSmoke(this.x, this.y);

}

function drawSmoke(x, y){
    fill(255, 255, 255, 100);
    ellipse(x + 30, y - 60, 20, 10);
    ellipse(x + 50, y - 70, 15, 8);
}


function makeBird(x, y) {
    var num = 50;
    var bird = {"bx": x, 
                "by": y, 
                "bsz": size, 
                "bsca": (map(pow(2, y / num), 0, pow(2, 300 / num), 1, 100)) / 35,
                "xvel": random(-10, 10) * (map(pow(2, y / num), 0, pow(2, 300 / num), 1, 100)) / 35,
                "yvel": random(-5, 5) * (map(pow(2, y / num), 0, pow(2, 300 / num), 1, 100)) / 35,
                };
    bird.draw = birdDraw;
    bird.draw2 = birdDraw2;
    return bird;
}

function birdDraw(){
    noFill();
    stroke(0);
    strokeWeight(2);
    push();
    translate(this.bx, this.by);
    scale(this.bsca);
    ellipseMode(CENTER); 
    arc(35, 35, 100, 100, PI * 1.25, PI * 1.5);
    arc(-35, 35, 100, 100, PI * 1.5, PI * 1.75);
    fill(0);
    ellipse(0, 0, 5, 5); 
    pop();
}

function birdDraw2(){
    noFill();
    stroke(0);
    strokeWeight(2);
    push();
    translate(this.bx, this.by);
    scale(this.bsca);
    rotate(PI/10);
    arc(35, 35, 100, 100, PI * 1.25, PI * 1.5);
    fill(0);
    ellipse(0, 0, 5, 5); 
    pop();

    push();
    translate(this.bx, this.by);
    scale(this.bsca);
    rotate(-PI / 10);
    arc(-35, 35, 100, 100, PI * 1.5, PI * 1.75);
    pop();
}

//make raccoon
function makeRac(x, y){
    var rac;
    var num = 50;
    rac = {
        "rx": x ,
        "ry": y, 
        "rsz": size,
        "bsca": (map(pow(2, y / num), 0, pow(2, 300 / num), 1, 100)) / 400,
        "vel": random(-2, 2) * (map(pow(2, y / num), 0, pow(2, 300 / num), 1, 50)) / 35
    };
    rac.draw = racDraw;
    return rac;
}

//draw raccoon
function racDraw(){
    var inv = -1;
    push();
    translate(this.rx, this.ry);
    fill(0);
    noStroke();
    beginShape();
    if (this.vel < 0){
        scale(this.bsca, this.bsca);
    } else{
        scale(this.bsca * -1, this.bsca);
    }
    vertex(0, 0);
    vertex(5, -10);
    vertex(3, -20);
    vertex(7, -30);
    vertex(5, -40);
    vertex(8, -45);
    vertex(20, -40);
    vertex(65, -55);
    vertex(85, -65);
    vertex(150, -60);
    vertex(190, -30);
    vertex(180, 20);
    vertex(190, 50);
    vertex(180, 80);
    vertex(170, 80);
    vertex(170, 75);
    vertex(175, 73);
    vertex(176, 55);
    vertex(140, 25);
    vertex(110, 25);
    vertex(80, 80);
    vertex(70, 80);
    vertex(70, 75);
    vertex(75, 75);
    vertex(80, 50);
    vertex(70, 10);
    vertex(50, 10);
    vertex(30, 5);
    vertex(10, 10);
    vertex(0, 0);
    endShape();

    beginShape();
    vertex(200, -25);
    vertex(192, 10);
    vertex(200, 18);
    vertex(210, -20);
    endShape();

    beginShape();
    vertex(220, -15);
    vertex(230, -8);
    vertex(220, 30);
    vertex(210, 22);
    endShape();

    beginShape();
    vertex(240, -3);
    vertex(250, 5);
    vertex(242, 20);
    vertex(232, 25);
    endShape();

    beginShape();
    fill(255);
    vertex(50, 10);
    vertex(30, -15);
    vertex(20, -13);
    vertex(15, -5);
    vertex(15, -5);
    vertex(20, 0);
    vertex(26, 0);
    vertex(35, 6);
    endShape();

    fill(0);
    ellipse(23, -8, 5, 5);
    rect(112, 50, 15, 7);

    rotate(PI / 4);
    rect(60, -40, 10, 40);
    rect(120, -80, 10, 30);
    pop();
}

//interactions
function keyPressed(){
    if(keyCode === RIGHT_ARROW){
        if (rachouseCount < houseList.length){
            var selhouse = int(random(0, houseList.length));
            while (houseList[selhouse].rh == true){
                selhouse = int(random(0, houseList.length));
            }
            houseList[selhouse].rh = true;
        }
    }
    if(keyCode === LEFT_ARROW){
        birdList.push(makeBird(random(0, 500), random(0, 200)));
    }
}

//Linear gradient code from p5js examples https://p5js.org/examples/color-linear-gradient.html
function setGradient(x, y, w, h, c1, c2, axis) {
    noFill();
    if (axis == Y_AXIS) {  // Top to bottom gradient
        for (var i = y; i <= y + h; i++) {
            var inter = map(i, y, y + h, 0, 1);
            var c = lerpColor(c1, c2, inter);
            stroke(c);
            line(x, i, x + w, i);
        }
    }  
}

In this project I want to create an interactive animation on cohabitation wiht urban wildlife in cities. As we are displacing natural habitats to make way for urban sprawl, effects of a loss of biodiversity and edge effects from habitat fragmentation are becoming more pronounced. In my studio I am currently working on a thesis project dealing with the environment and cohabitation/negotiation of boundaries between human and more-than-human species, and creating installations for endangered species as well as synanthropic species to share urban space. I am inspired by the works of Joyce Hwang and Sarah Gunawan , and I want to create an animation that documents the vision of such installation projects and their impacts on our environment. Especially the bird landing pads and composting chimneys for raccoons.

In this animation, trains pass by at a certain interval of time, pressing left arrow adds a bird, and for every 3 birds added, an artificial bird nest attached to trees will pop up. (Nests will start disappearing when birds leave the screen). Pressing right arrow adds a compost chimney attached to houses, and every chimney attracts 2 raccoons.

Working on this project I spent a large chunk of my time illustrating the creatures and houses which in hindsight could have been done much easier if I just drew them and upload them to imgur. I also had trouble with overlapping objects and had to create functions that sort the order or the object array and also draws objects outside of the boundary of other objects. I feel like I reviewed everything we learned this semester through this project.

Sound Test

 

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

Romi Jin – Project-12-Final Project

sketch

/*
Romi Jin
Section B
rsjin@andrew.cmu.edu
Project-12
*/

var pic = {};
pic.bunny = "BUN.gif"; //bunny gif
pic.cloud = "cloud.png"; //cloud ground and movable
pic.carrot = "carrot.png"; //carrots to collect

var posX = 50; //start position
var posY = 50;
var speed = 4;
var jump_height = 15;
var jump = 38;
var left = 37;
var right = 39;
var moveinterval;
var gravityinterval;
var constant = 1;
var bound = 8;
var size = 5000;
var keysDown = [];
var stage;
var bunny;
var carrotnumber;
var above = 1;
var toleft = 3;
var onground = false;
var canjump = true;
var timer = 500;
var BOUNCE_FACTOR = 2;
var movingclouds = [];
var carrots = [];
var objects = [];
var start = 0;
var moveleft = 0;
var moveright = 1;
var movex = moveright;
var objectnumber;

function move(){
  //move bunny and define key pressed functions
  for (key in keysDown){
    switch (keysDown[key]){
      case right:
        posX += speed;
        if (stage.scrollLeft < size)
          stage.scrollLeft = bunny.offsetLeft-(stage.offsetWidth/2)+(bunny.offsetWidth/2);
        if (onground)
          bunny.src = pic.bunny;
        movex = moveright;
        break;
      case jump:
        if (onground & canjump){
          canjump = false;
          setTimeout(function(){canjump=true;},timer);
          constant = -jump_height;
          posY -= jump_height;
          onground = false;
          bunny.src = (movex==moveright) ? pic.bunny : pic.bunny;
        }
        break;
      case left:
        if (onground)
          bunny.src = pic.bunny;
        posX -= speed;
        stage.scrollLeft = bunny.offsetLeft-(stage.offsetWidth/2)+(bunny.offsetWidth/2);
        movex = moveleft;
        break;
      default:
    }
  }
  
  start++;
  //how clouds move up and down
  for (i in movingclouds){
    movingclouds[i].style.top = 150+50*Math.sin(start/50)+"px";
  }
  //when bunny stops in front of objects
   bunnystop();
  //render bunny
  render();
}

function collect(x){
  //collects carrots
  if (carrots.indexOf(x) > -1){
    remove(carrots,x);
    remove(objects, x);
    stage.removeChild(x);
    takeCarrot();
    return true;
  }
  return false;
}

function bunnyjump(a, b, c, d){
  if (c >= b) {
    d();
    return;
  }
  a.style.top = a.offsetTop - c + "px";
  setTimeout(function(){bunnyjump(a, b, c+1, d)}, 50);
}

function takeCarrot(){
  //adds to number of carrots in upper left corner -- keeps count / score
  carrotnumber.innerHTML = parseInt(carrotnumber.innerHTML)+1;  
}

function bunnystop(){
  //when bunny stops moving
  if (posX < stage.offsetLeft) posX = 5;
  if (posX+bunny.offsetWidth>size) posX = size - bunny.offsetWidth;
  
  onground = false;
  objectnumber = 0;
  
  for (c in objects){
      switch (bunnybounds(objects[c])){
        case above:
          if (collect(objects[c])) break;
          posY = objects[c].offsetTop-bunny.offsetHeight;
          onground = true;
          if ((objects[c])) break;
          speed = speed;
        case toleft:
          if (collect(objects[c])) break;
          posX = objects[c].offsetLeft-bunny.offsetWidth;
          if (!canjump)
            speed = 1;
          break;
      }
  }
}

function bunnybounds(x){
  //keep bunny outside objects
  if (posY+bunny.offsetHeight>x.offsetTop & 
    (posX + (bunny.offsetWidth/2)) > x.offsetLeft &&
    (posX + (bunny.offsetWidth/2)) < (x.offsetLeft+x.offsetWidth) &&
    posY < x.offsetTop &&
    posY+bunny.offsetHeight<(x.offsetTop+x.offsetHeight))
    return above;
  if (posX+bunny.offsetWidth>x.offsetLeft & 
    (posY + (bunny.offsetHeight/2)) < (x.offsetTop+x.offsetHeight) && 
    posX < x.offsetLeft && 
    (posY + (bunny.offsetHeight/2)) > x.offsetTop)
    return toleft;
  return 0;
}

function render(){
  //render bunny start position
  bunny.style.left = posX + "px";
  bunny.style.top = posY + "px";
}

function renderWorld(){
  //create all objects and defines elements of each
  stage = document.getElementById('stage');
  bunny = document.getElementById('bunny');
  carrotnumber = document.getElementById('carrotnumber');
  
  var clouds = [];
  for (var i = 0; i < 24; i++){
    clouds.push(cloudsurface(null, pic.cloud, i*40, stage.offsetHeight-35));
    objects.push(clouds[i]);
  }
  
  setTimeout(function(){
    var a = cloudsurface(clouds[9], pic.cloud);
    var b = cloudsurface(clouds[8], pic.cloud, -10, -100);
    objects.push(b);
    carrots.push(b);
    
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[6], pic.cloud, i*20, -40);
      objects.push(x);
      objects.push(x);

    }
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[4], pic.cloud, i*20, -40);
      objects.push(x);
      objects.push(x);
    }

    var c = cloudsurface(clouds[10], pic.cloud);
    var d = cloudsurface(clouds[20], pic.cloud);
    movingclouds.push(c);
    movingclouds.push(d);
    
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[7], pic.carrot, i*30, -10);
      objects.push(x);
      carrots.push(x);
    }
    for (var i = 0; i<4; i++){
      var x = cloudsurface(clouds[6], pic.carrot, i*30+5, -100-i*30);
      objects.push(x);
      carrots.push(x);
    }
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[10], pic.carrot, i*30, -230);
      objects.push(x);
      carrots.push(x);
    }
    
    for (var i = 1; i<4; i++){
      var x = cloudsurface(clouds[15], pic.cloud, i*20, -60);
      objects.push(x);
      objects.push(x);
      
      var x = cloudsurface(f, pic.carrot, 12, -i*30-140);
      objects.push(x);
      carrots.push(x);
    }
    
    for (var j = 0; j < 9; j++){
      for (var i = 0; i<11; i++){
        if (i <= j) continue;
        var x = cloudsurface(clouds[20], pic.cloud, i*20, -j*20);
        objects.push(x);
      }
    }
    
    var e = cloudsurface(clouds[10], pic.cloud);
    objects.push(e);
    var f = cloudsurface(clouds[20], pic.cloud);
    objects.push(a);
    objects.push(b);
    objects.push(c);
    objects.push(d);
    objects.push(f);

  },1000);
}

function cloudsurface(surface, pic, left, y){
  //cloud ground positioning
    var cloud = document.createElement("img");
    cloud.src = pic;
    stage.appendChild(cloud);
    cloud.style.position = "absolute";
    cloud.style.top = ((surface != null) ? (surface.offsetTop-cloud.offsetHeight + (y||0)) : y) + "px";
    cloud.style.left = ((surface != null) ? surface.offsetLeft + (left||0) : left) + "px";
    return cloud;
}

function gravity(){
  //bunny positioning in terms of gravity
  if (!onground)
    posY += constant;
  constant++;
  if (constant > bound) constant = bound;
}

function remove(x, y){
  //removes the carrots
  if (x.indexOf(y) > -1)
    x.splice(x.indexOf(y),1);
}

function onkeyDown(i){
  //defines key down pressed
  var down = window.event || i;
  var keypress = i.charCode || i.keyCode;
  if (down.preventDefault)
    down.preventDefault();
  else{
    down.returnValue = false;
  }
  if (keysDown.indexOf(keypress) > -1) return;
  keysDown.push(keypress);
  return false;
}

function onKeyUp(i){
  //allows bunny to move backwards
  var down = window.event || i;
  var keypress = i.charCode || i.keyCode;
  remove(keysDown, keypress);
}

function loadPics(load){
  //load all images and gifs
    for (i in pic){
      var img = new Image();
      img.src = pic[i];
      img.onload = (function(h,i){
          return function(){
            i = h;
          }
        })(img.src, pic[i]);

    }
    load();
}

$(document).ready(function(){
  loadPics(function(){
    renderWorld();
    stage.scrollLeft = 0;
  });
  setTimeout(function(){
    moveinterval = setInterval(function(){move();},15);
    gravityinterval = setInterval(function(){gravity();},30);
    $(this).keydown(onkeyDown);
    $(this).keyup(onKeyUp);
  },500);
});
    

For my final project, I initially tried to create like mario run, but it ended up being a lot more complicated than I had expected, so I made the game a lot more simpler than what I had imagined it would be. The bunny can move left and right to collect carrots while running and jumping on clouds (some move, some don’t), and the goal is to collect all of the carrots. I have a separate js file and text in the html file, so I am not sure how to upload them all and make the file show up on WordPress, so I have attached a screenshot of what the final product looks like on my screen:

Austin Treu – Final Project

atreu-final_project

How to run: download and unzip the folder, then open the index.html file in your browser of choice, mine being Firefox.

For my final project, I worked utilizing turtle graphics to create a game and drawing software. I used the turtles like a snake from the game of the same name. Thus, I decided on the name Snakle for my game. The main game is a two player competitive game in which each player is trying to make their snakle the longest by outlasting the other player. Player one is blue and player two is red. The game keeps track of score and displays the winner after each round, so the players can continue playing to a certain score. The drawing feature is based off of a similar concept to that of the game, where you control a single snakle in four directions with a color palette. It works very similarly to an Etch-A-Sketch, but you can click to move the snakle elsewhere.

Start screen:

Help Screen:

Game:

Etch-A-Sketch: