///////////////////////////////////////////////////////////////////////////
// Author: Justin Vrieling
// Made for Media Computation at Sheridan College
// October 2018
//
// - Click the duck to spook it and make it fly! Move your mouse over it in
// flight to change its direction!
// - Make jeremy the duck hit a UFO to make it crash! The ufo speeds up
// whenever you hit it, and slows down if you miss.
//
///////////////////////////////////////////////////////////////////////////
//declare variables for use later
float waterOffset;
float starAlpha = 100;
//A couple of variables to handle the duck (HMM, IF ONLY I COULD USE ARRAYS OR CLASSES)
int duckCount = 5;
float duckSpeed = 2;
float ducksX = random(0, 400);
float ducksY = random(240, 390);
float ducksDirection = 0;
float ducksRise = 0;
float duckLanding = 400;
int dirCooldown = 0;
float wingOffset = 0;
//Variables for the UFOs
float ufoX = -100;
float ufoY = 100;
float ufoSpeed = 1;
int ufoCooldown = 10;
int score = 0;
//Coordinates for the stars
float star1X = random(0, 400);
float star1Y = random(0, 240);
float star2X = random(0, 400);
float star2Y = random(0, 240);
float star3X = random(0, 400);
float star3Y = random(0, 240);
float star4X = random(0, 400);
float star4Y = random(0, 240);
float star5X = random(0, 400);
float star5Y = random(0, 240);
void setup() {
size(400, 400);
noStroke();
}
void draw() {
frameRate(60);
background(0);
//Modify the variables that need to change with each frame
starAlpha += random(-30, 30);
waterOffset = 0+(sin(frameCount*0.05)*3);
moveDucks();
moveUfo();
if (dirCooldown > 0) {
dirCooldown--;
}
if (ufoCooldown > 0) {
ufoCooldown--;
}
//draw all the things
drawLake();
drawStars();
drawUfo();
drawShimmer();
drawDucks();
}
/////////////////////
// UFO FUNCTIONS
///////////////////////
void moveUfo() {
//Move the ufo
if (ufoCooldown <= 0) {
ufoX+=ufoSpeed;
}
//if it goes off screen reset it
if (ufoX > width+100) {
resetUfo();
}
//if it hits the duck, make it go boom and add score and speed it up
if (ducksX >= ufoX-20 && ducksX <= ufoX+20 && ducksY <= ufoY+20 && ducksY >= ufoY-20) {
score++;
ufoSpeed = (ufoSpeed + 0.1) * 1.2;
fill(255, 0, 0);
ellipse(ufoX, ufoY, 70, 70);
frameRate(2);
print("BOOM! Score: " + score + "\n");
resetUfo();
}
}
void resetUfo() {
//Reset the ufo to the left side, and set the cooldown so it doesn't come right away
ufoCooldown = 80;
ufoX = -50;
ufoY = random(70, 150);
ufoSpeed *= 0.9;
}
void drawUfo() {
//Draw the ufo
//Blue orb thing
fill(0, 200, 200);
ellipse(ufoX, ufoY-10, 25, 25);
//Red body. Shift the colour based on score
fill(255-(score*20), 0+(score*20), 0+(score*20));
ellipse(ufoX, ufoY, 50, 20);
}
//////////////////////
// DUCK FUNCTIONS
//////////////////////
void drawDucks() {
//Draw a duck relative to the coordinates from the lists.
//The conditional makes the duck face where it's going
if (ducksDirection >= 0) {
//body
fill(#4E504A);
ellipse(ducksX, ducksY+waterOffset, 40, 20);
//wing
fill(#41423D);
triangle(ducksX-15, ducksY+waterOffset+wingOffset, ducksX+5, ducksY-6+waterOffset, ducksX+5, ducksY+7+waterOffset);
//head
fill(#1B6C3D);
ellipse(ducksX+15, (ducksY+waterOffset)-10, 15, 15);
//beak
fill(#FFDD95);
triangle(ducksX+21, (ducksY+waterOffset)-7, ducksX+26, (ducksY+waterOffset)-9, ducksX+21, (ducksY+waterOffset)-12);
//eye
fill(0);
ellipse(ducksX+17, (ducksY+waterOffset)-12, 3, 3);
} else {
//body
fill(#4E504A);
ellipse(ducksX, ducksY+waterOffset, 40, 20);
//wing
fill(#41423D);
triangle(ducksX+15, ducksY+waterOffset+wingOffset, ducksX-5, ducksY-6+waterOffset, ducksX-5, ducksY+7+waterOffset);
//head
fill(#1B6C3D);
ellipse(ducksX-15, (ducksY+waterOffset)-10, 15, 15);
//beak
fill(#FFDD95);
triangle(ducksX-21, (ducksY+waterOffset)-7, ducksX-26, (ducksY+waterOffset)-9, ducksX-21, (ducksY+waterOffset)-12);
//eye
fill(0);
ellipse(ducksX-17, (ducksY+waterOffset)-12, 3, 3);
}
}
void mouseClicked() {
//When mouse is clicked, Check if it was on the duck
if (mouseX <= ducksX+20 && mouseX >= ducksX-20 && mouseY <= ducksY+20 && mouseY >= ducksY-20) {
scareDucks();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// A function to handle movement of the ducks. Handles exiting the play space as well
void moveDucks() {
//If mouse is over the duck, make it change direction
if (dirCooldown == 0 && mouseX <= ducksX+20 && mouseX >= ducksX-20 && mouseY <= ducksY+20 && mouseY >= ducksY-20) {
ducksDirection *= -1;
dirCooldown = 40;
}
//If the duckDirection isn't zero, it's in flight
if (ducksDirection != 0) {
wingOffset = (sin(frameCount*0.3)*15);
//The variables will always be appropriate so these equations will make them rise or fall.
ducksY -= (duckSpeed*ducksRise);
ducksX += duckSpeed*ducksDirection;
//make sure the ducks don't go off screen
if (ducksX <= 0 || ducksX >= 400) {
ducksDirection *= -1;
}
//make sure they don't go off the top either
if (ducksY < 50) {
ducksRise *= -1;
}
//When the duck is in the air decide on the landing Y coordinate
if (duckLanding == 400 && ducksY <= 200) {
duckLanding = random(240, 380);
}
//When the duck hits the Y landing, make it stop flying and reset stuff.
if (ducksY >= duckLanding) {
ducksDirection = 0;
duckLanding = 400;
wingOffset = 0;
}
}
}
void scareDucks() {
//Don't let the direction be zero.
while (ducksDirection == 0) {
ducksDirection = round(random(-1, 1));
ducksRise = 1;
}
}
//////////////////////
// LAKE FUNCTIONS
//////////////////////
void drawShimmer() {
//Draw the shimmering reflection of the moon on the lake
fill(255, 100);
ellipse(210+(sin(frameCount*0.1)*4), 245+waterOffset, 30, 5);
ellipse(190+(sin(frameCount*0.11)*5), 245+waterOffset, 40, 6);
ellipse(210+(sin(frameCount*0.12)*5), 250+waterOffset, 35, 4);
ellipse(230+(sin(frameCount*0.1)*6), 246+waterOffset, 20, 4);
ellipse(240+(sin(frameCount*0.16)*4), 243+waterOffset, 10, 3);
ellipse(180+(sin(frameCount*0.08)*7), 242+waterOffset, 45, 4);
ellipse(220+(sin(frameCount*0.1)*10), 242+waterOffset, 15, 4);
}
void drawStars() {
//Draw the stars
fill(255, random(90, 150));
ellipse(star1X, star1Y, 3, 3);
ellipse(star2X, star2Y, 3, 3);
ellipse(star3X, star3Y, 3, 3);
ellipse(star4X, star4Y, 3, 3);
ellipse(star5X, star5Y, 3, 3);
fill(255, 70);
//Draw the shimmer around the stars.
//Using sin() and random to make them glimmer real cool
ellipse(star1X, star1Y, 4+(sin(frameCount*random(0.01, 0.05))*3), 4+(sin(frameCount*random(0.01, 0.05))*3));
ellipse(star2X, star2Y, 4+(sin(frameCount*random(0.01, 0.05))*3), 4+(sin(frameCount*random(0.01, 0.05))*3));
ellipse(star3X, star3Y, 4+(sin(frameCount*random(0.01, 0.05))*3), 4+(sin(frameCount*random(0.01, 0.05))*3));
ellipse(star4X, star4Y, 4+(sin(frameCount*random(0.01, 0.05))*3), 4+(sin(frameCount*random(0.01, 0.05))*3));
ellipse(star5X, star5Y, 4+(sin(frameCount*random(0.01, 0.05))*3), 4+(sin(frameCount*random(0.01, 0.05))*3));
//Draw the moon//
fill(255);
ellipse(200, 70, 40, 40);
fill(#FFEAD0);
//craters
ellipse(210, 60, 7, 7);
ellipse(195, 70, 9, 9);
ellipse(190, 65, 5, 5);
ellipse(200, 65, 5, 5);
ellipse(205, 80, 5, 5);
ellipse(185, 80, 4, 4);
}
void drawLake() {
//Draw the lake, use a loop for the gradient
rectMode(CORNER);
for (int i = 0; i < 200; i += 20) {
//Set the colour based on how low on the screen
fill(33-(i/5), 42-(i/5), 66-(i/5));
//Draw a rectangle, using water offSet to make it wave
rect(0, ((240+i)+waterOffset), 400, 30);
}
}