//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.)
//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!
//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);
}
}
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!
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:
Download .zip file and extract it to your computer
Open a command prompt, and type cd “path to file” (ex: C:\Users\Cassie Howard\Downloads\cmhoward-final-project\template-all)
Then connect to python “python -m http.server”
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).
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. )
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.
//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.
/*
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:
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.