/********************************************************** 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); }