// Nadia Susanto
// nsusanto@andrew.cmu.edu
// Section B
// Final Project
var terrainSpeed = 0.0005;
var terrainDetail = 0.003;
var clouds = [];
var pipes = [];
var birdY = 300;
var birdX = 65;
var birdGravity = 0.75;
var birdVelocity = 0;
var birdUpForce = -18;
var secs = 0;
function setup() {
createCanvas(600, 600);
background(135,235,250);
pipes.push(makePipe());
//initalizing clouds
for (var x = 0; x < 5; x++) {
var cx = random(width);
clouds[x] = makeClouds(cx);
}
frameRate(60);
}
function draw() {
//blue sky
background(135,235,250);
//show mountains and waves
makeMountains();
makeWaves();
//show clouds
addNewClouds();
updateAndDisplayClouds();
removeCloudsOutofView();
//pipes
addNewPipes();
updateAndDisplayPipes();
//bird
drawBird();
updateBird();
//collision detection for bird with pipe
topCollision();
bottomCollision();
if (frameCount % 60 == 0) {
secs += 1;
}
//score
fill("black");
textSize(30);
textAlign(LEFT);
text("TIME = " + secs, 5, 50);
}
//collision for bird with top pipe
function topCollision() {
for (var i = 0; i < pipes.length; i++) {
if ((birdY < pipes[i].top + 30) & (birdX > pipes[i].x && (birdX < pipes[i].x + pipes[i].w))) {
gameOver();
}
}
}
//collision for bird with bottom pipe
function bottomCollision() {
for (var i = 0; i < pipes.length; i++) {
if ((birdY > pipes[i].top + 150) & (birdX > pipes[i].x && (birdX < pipes[i].x + pipes[i].w))) {
gameOver();
}
}
}
//game over function that stops the game when triggered
function gameOver() {
fill("red");
textAlign(CENTER);
textSize(60);
text("GAME OVER", width/2, height/2);
noLoop();
}
//constantly calling the pipes
function updateAndDisplayPipes() {
for (var i = 0; i < pipes.length; i++) {
pipes[i].move();
pipes[i].draw();
}
}
function addNewPipes() {
if (frameCount % 150 == 0) {
pipes.push(makePipe());
}
}
//moving the pipes right to left
function movePipe() {
this.x -= this.speed;
}
function drawPipe() {
noStroke();
//top pipe
fill(112,186,45);
rect(this.x, 0, this.w, this.top);
rect(this.x - 5, this.top - 2, this.w + 10, 20, 10);
//bottom pipe
rect(this.x, height, this.w, this.top - height + 150);
rect(this.x - 5, this.top + 135, this.w + 10, 20, 10);
}
//object for pipe
function makePipe() {
var pipe = {x: width,
w: 50,
top: random(50, height/2),
speed: 1.5,
move: movePipe,
draw: drawPipe
}
return pipe;
}
//drawing the bird
function drawBird() {
//legs
fill(0);
ellipse(birdX - 10, birdY + 15, 3, 10);
ellipse(birdX + 10, birdY + 15, 3, 10);
//halo
noFill();
stroke("gold");
ellipse(birdX, birdY - 20, 40, 5);
//body
fill("yellow");
ellipse(birdX, birdY, 35, 35);
//eye
fill(0);
ellipse(birdX + 5, birdY - 5, 5);
//beak
fill("orange");
triangle(birdX + 18, birdY - 4, birdX + 23, birdY, birdX + 18, birdY + 4);
}
//implementing velocity and gravity
function updateBird() {
birdVelocity += birdGravity;
//air resistance
birdVelocity *= 0.9;
birdY += birdVelocity;
//making sure it doesnt go beyond top and bottom of canvas
if (birdY > height) {
birdY = height;
birdVelocity = 0;
}
if (birdY < 0) {
birdY = 0;
birdVelocity = 0;
}
}
//adding up force to bird velocity
function birdUp() {
birdVelocity += birdUpForce;
}
//if space bar pressed, trigger the bird to go up
function keyPressed() {
if (key == ' ') {
birdUp();
}
}
//constantly calling the clouds
function updateAndDisplayClouds() {
for (var x = 0; x < clouds.length; x++){
clouds[x].move();
clouds[x].draw();
}
}
function removeCloudsOutofView() {
var cloudsKeep = [];
for (var x = 0; x < clouds.length; x++) {
if (clouds[x].x > 0) {
cloudsKeep.push(clouds[x]);
}
}
clouds = cloudsKeep; //remember the clouds
}
function addNewClouds() {
var cloudProb = 0.01;
//if random number less than probability then a new cloud is shown
if (random(0, 1) < cloudProb) {
clouds.push(makeClouds(width));
}
}
function cloudsMove() {
//move the clouds from right to left
this.x -= this.speed;
}
function drawClouds() {
//draw the white clouds
fill("white");
ellipse(this.x, this.y, this.width, 10);
ellipse(this.x - 25, this.y - 10, 35, 30);
ellipse(this.x + 25, this.y - 10, 30, 30);
ellipse(this.x + 5, this.y - 15, 40, 25);
}
function makeClouds(cloudX) {
//creating object for cloud
var cloud = {x: cloudX,
y: 50,
width: random(50, 100),
speed: 0.50,
move: cloudsMove,
draw: drawClouds}
return cloud;
}
//adopted the terrain starter code to make mountains in background
function makeMountains() {
noStroke();
fill(127,221,136);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail*3) + (millis() * terrainSpeed);
var y = map(noise(t), 0, 1, height/4, height/3);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
//adopted the terrain starter code to make ocean waves
function makeWaves() {
noStroke();
fill(1, 108, 194);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail/3) + (millis() * terrainSpeed/2);
var y = map(noise(t), 0, 1, height/2, height);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
For my final project I made angel bird! I have always been a gamer at heart and love competition whether it be beating my peers or my personal bests. Originally for my proposal I wanted to do scream go hero but had difficulties with voice recognition. Flappy bird was my backup and I am really happy with the way it turned out. I used my knowledge of objects to create the generative backgrounds and the pipes, and I believe my angel bird with a halo is pretty cute.
How the game works:
The game automatically starts and all you have to do is press the space bar to make the bird go up. Instead of scoring, you want to beat your personal best times as you want to see how long you can go without the dreaded “GAME OVER.” Enjoy!