/**********************************************************
Interactive Toy --Bouncing Ball
by: Filink Cao (991399732)
use your mouse to control the bouncing ball horizontally(No, you can't stop it from bouncing lol).
Avoid small balls and try to survive as long as you can!
Press F to use your skill to stun the small balls, however it cost your magic..... Magic restores automatically.
Actually its easier without magic, just dont use it.
Oh, every time you bounce you will get bigger...
after you die be sure to check your score below! And press SPACE to restart!
************************************************************/
//attributes for ball
float ballPositionX, ballPositionY, ballVelocity,shadeX, shadeY;
float magic, damage ;
int point;
//attributes for enemey
float foe2PositionY, rfoe2PositionY, foe3PositionX,shade2X,shade2Y,shade3X,shade3Y;
float foe2PositionX, foe2Velocity, foe3PositionY, foe3Velocity, attraction;
//other attributes
boolean displayscore, gameOver, magicUsing;
void setup ()
{
size (400, 400);
//assigning the initial value
ballPositionX = 200;
point = 0;
damage = 0;
ballPositionY = 0;
ballVelocity = 0;
rfoe2PositionY = 0;
foe3PositionX = 0;
foe2PositionX = 160;
foe2Velocity = 16;
foe3PositionY = 250;
foe3Velocity = 20;
attraction = 0.5;
magic=255;
//foe2PositionXup = false;
//foe3PositionYup = true;
displayscore = false;
gameOver = false;
magicUsing = false;
}
void draw ()
{
//check the health, if damagen taken is over 200, game is over.
if (damage >= 180)
{
gameOver = true;
}
//If game is over, display the gameover screen and a message contains the score.
if (gameOver == true)
{
gameoverScreen (200);
//Display the score, a switch is added to ensure it only display once.
if (displayscore==false)
{
println ("YOU DIED. YOUR SCORE WAS " + point );
println ("\nPress SPACE to reset :D");
displayscore = true;
}
}
//else continue the game.
if (gameOver == false)
{
//THE FOLLOWING SENTENCES ARE FOR TESTING USES
// print ( foe2PositionX+ " ");
// print (foe3PositionY + "\n");
//if (foe2Velocity==0)
//print (foe2PositionX+ " " + foe2PositionY + "\n");
//if (foe3Velocity ==0 )
//print (foe3PositionX + " " + foe3PositionY + "\n");
//if (ballVelocity==0)
//print (ballPositionY + "\n");
/****************************
update
****************************/
//updating the position of the bouncing ball
updateBall();
//updating the positions of enemy based on whether the magic is being used
//*the enemy 1 doesn't exist
//*the "rfoe2PositionY" is enemy 2's distance to the bottom
if (magicUsing == true)
{
foe2PositionY+= random(-2, 2);
foe3PositionX+= random(-2, 2);
foe2PositionX+= random(-2, 2);
foe3PositionY+= random(-2, 2);
} else
{
rfoe2PositionY = (rfoe2PositionY+1)%420;
foe2PositionY = 420-(rfoe2PositionY);
foe3PositionX = (foe3PositionX+2)%420;
wave( foe2Velocity, foe2PositionX, 2);
wave( foe3Velocity, foe3PositionY, 3);
}
shade2X =map (foe2PositionX, 0, width, -30, width+30);
shade3X =map (foe3PositionX, 0, width, -30, width+30);
shade2Y = foe2PositionY;
shade3Y = foe3PositionY;
//update the magic
updateMagic ();
//update the damage
updateDamage ();
/***********************
draw
***********************/
//draw a back ground
background (255);
//draw the magic bar
drawMagicBar ();
//draw the life bar, which is a square gets smaller as taking damage
drawHealthBar ();
//draw the ball
drawBall ();
//draw the enemy and their shadows
fill (50, 50,50, 150);
ellipse (shade2X, shade2Y, 35,35);
ellipse (shade3X, shade3Y, 35,35);
fill (185, 0, 59);
ellipse (foe2PositionX, foe2PositionY, 30, 30);
ellipse (foe3PositionX, foe3PositionY, 30, 30);
//damage effect, the screen flashes red when taking damage, as damage taken increased, the screen starts to flicker.
if (sqrt(sq(ballPositionX-foe2PositionX)+sq(ballPositionY-foe2PositionY))<(30+2.5*point)||sqrt(sq(ballPositionX-foe3PositionX)+sq(ballPositionY-foe3PositionY))<(30+2.5*point))
{
fill (255, 0, 0, 170);
rect (0, 0, width, height);
}
if (damage>60 && damage <= 120)
gameoverScreen (80);
if (damage>120)
gameoverScreen (100);
}
}
/************************
EVENTS
***********************/
void keyPressed()
{
//after game over, press any key can reset the game
if (gameOver == true&& (key == ' '))
{
setup();
}
//When game is in progress, press F to cast the magic
if (gameOver == false &&( key == 'f'||key == 'F'))
{
if (magic >0)
{
magicUsing = true;
}
if (magic <= 0 )
{
magicUsing = false;
}
}
}
void keyReleased()
{
if (gameOver == false &&( key == 'f'||key == 'F'))
{
if (magic < 0)
{
magic = 0;
}
magicUsing = false;
}
}
/****************************
FUNCTIONS
****************************/
//A function generating vibration
void wave (float fv, float fy, int fn)
{
if (fy<200)
{
fv += round(attraction * 100.0) / 100.0;
}
if (fy>200)
{
fv -= round(attraction * 100.0) / 100.0;
}
fv =round(fv * 100.0)/ 100.0;
fy = fy+fv/2;
//returning variables
if (fn==2)
{
foe2PositionX = fy;
foe2Velocity = fv;
}
if (fn ==3)
{
foe3PositionY = fy;
foe3Velocity=fv;
}
}
//a function generates the game over screen
void gameoverScreen (int transparency)
{
for (int i=0; i < height; i+=50)
{
for (int k=0; k < width; k+=50)
{
noStroke ();
fill (random (0, 100), 0, 0, random(transparency, transparency+50));
rect (k, i, 50, 50);
}
}
}
//a funtion updates the position of the ball
void updateBall()
{
//Updating the Y position of the ball
//********************note to Alex, change the below variable to 0.98 and the weird thing happens.*****************************
ballVelocity += 0.95;
//this rounding function should fix the rounding errors caused by the use of floats, from Alex
ballVelocity = round(ballVelocity * 100.0)/ 100.0;
ballPositionY+=ballVelocity;
//"Issue is that the floating point number has rounding errors, causeing your ball to not make a perfect parabolla and lose velocity"--Alex Massart
if (ballPositionY>height)
{
ballPositionY=height;
ballVelocity = -ballVelocity;
point+=1;
}
shadeY = ballPositionY;
//updating the X position of the ball
if (mouseX>ballPositionX)
ballPositionX+=(mouseX-ballPositionX)/20;
if (mouseX<ballPositionX)
ballPositionX-=(ballPositionX-mouseX)/20;
shadeX = map (ballPositionX, 0, width, -30, width+30);
}
void updateMagic ()
{
//When F key is held, continuously decreases the magic.
if (keyPressed == true&&(key == 'f'||key == 'F'))
{
magic-=5;
}
//When F is not pressed, restore the magic
if (keyPressed==false && magic< 255)
{
magic+= 1;
}
}
void updateDamage ()
{
//increase the damage taken as the ball touches the enemies
if (sqrt(sq(ballPositionX-foe2PositionX)+sq(ballPositionY-foe2PositionY))<(30+2.5*point)||sqrt(sq(ballPositionX-foe3PositionX)+sq(ballPositionY-foe3PositionY))<(30+2.5*point))
{
damage+=1;
}
}
void drawMagicBar ()
{
noStroke();
fill (magic);
rect ( 0, 0, width, height);
}
void drawHealthBar ()
{
fill (damage+55, 0, 255-(damage+55));
rectMode (CENTER);
rect (200, 200, 360-damage*2, 360-damage*2);
rectMode (CORNER);
}
//a function draws the ball
void drawBall ()
{
if (ballPositionY>=380)
{
noStroke();
fill (50, 50,50, 150);
ellipse (shadeX, shadeY, 70+5*point, 40+3*point);
noStroke();
fill (255, 152, 49);
ellipse (ballPositionX, ballPositionY, 60+5*point, 30+2*point);
} else
{
noStroke();
fill (50, 50, 50, 150);
ellipse (shadeX, shadeY, 60+3*point, 60+3*point);
noStroke();
fill (255, 152, 49);
ellipse (ballPositionX, ballPositionY, 50+3*point, 50+3*point);
}
//the ball's expression changes based on the damage taken.
rectMode (CENTER);
if (damage>=0 && damage <= 60)
{
fill (167, 238, 255);
rect (ballPositionX-12-0.07*(200-mouseX), ballPositionY-5, 8, 8);
rect (ballPositionX+12-0.07*(200-mouseX), ballPositionY-5, 8, 8);
}
if (damage>60 && damage <= 120)
{
fill (102, 211, 45);
rect (ballPositionX-12-0.07*(200-mouseX), ballPositionY-5, 15, 4);
rect (ballPositionX+12-0.07*(200-mouseX), ballPositionY-5, 15, 4);
}
if (damage>120)
{
fill (214, 104, 19);
arc (ballPositionX-12-0.07*(200-mouseX), ballPositionY-5, 15, 10, 0, PI);
arc (ballPositionX+12-0.07*(200-mouseX), ballPositionY-5, 15, 10, 0, PI);
}
rectMode (CORNER);
}