## ~ Game Design

### Challenge 5

And that's it! We're here. You now just need to add the "Game over" feature which is shown in the code below

### CHALLENGE :

1. Copy and paste the code below (this concludes the game)

2. See if you can improve and extend the program by creating your own requirements and additional objectives:

### CODE:

```import pygame
import random
import math

#Define variables wich represent the size of the map we want
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 300

#Create the ball class
class Ball:
def __init__(self, x, y, radius, color, screen):
#A ball need a position (x,y), a radius, a color and the screen where we will paint it, therefore
#the constructor will take these as arguments and save their values in variables of the ball class by using the word self
self.x = x
self.y = y
self.screen = screen
self.color = color

#The draw function will be responsible for drawing the ball in the screen
def draw(self):

#New class for the player's ball. This class extends Ball because it has the same base features but is more specific
class PlayerBall(Ball):
def __init__(self, x, y, radius, color, screen):
Ball.__init__(self, x, y, radius, color, screen)
#Add variables to the PlayerBall class for the cooldown of touching the green ball and the red ball
self.green_cooldown = 0
self.red_cooldown = 0

#The move function is responsible for changing the position of the ball based on the user input
def move(self, mv_type):
if mv_type == "UP":
self.y -= 2
elif mv_type == "DOWN":
self.y += 2
elif mv_type == "LEFT":
self.x -= 2
elif mv_type == "RIGHT":
self.x += 2

#If the ball has passed the bounds of the map then update it's position so that it stays inside
if self.x - self.radius < 0:
elif self.x + self.radius > SCREEN_WIDTH:
if self.y - self.radius < 0:
elif self.y + self.radius > SCREEN_HEIGHT:

#This function checks if the player's ball is touching another ball
def check_contact(self, greenBall, redBall):
#This variable will be returned with the summed value of the balls that are touching the player's ball
to_return = 0
#If the distance between the two centers is less that the sum of the radius of both balls then they are touching
if math.sqrt((self.y - greenBall.y) ** 2 + (self.x - greenBall.x) ** 2) < self.radius + greenBall.radius:
if self.green_cooldown == 0:
#Update the green ball cooldown and add 10 to the return variable
self.green_cooldown = 10
to_return += 10
#If the distance between the two centers is less that the sum of the radius of both balls then they are touching
if math.sqrt((self.y - redBall.y) ** 2 + (self.x - redBall.x) ** 2) < self.radius + redBall.radius:
if self.red_cooldown == 0:
#Update the red ball cooldown and subtract 10 to the return variable
self.red_cooldown = 10
to_return -= 10

#This class represents the green ball that gives points when the player's ball touches it
class GreenBall(Ball):
#Similarly to the player's ball, this class extends Ball but has two new variable
def __init__(self, x, y, radius, color, screen):
Ball.__init__(self, x, y, radius, color, screen)
#vx and vy are the velocity values for this ball and are generated randomly when a GreenBall object is created
self.vy = random.randint(0, 4) - 2
self.vx = random.randint(0, 4) - 2
while self.vy == 0 or self.vx == 0:
self.vy = random.randint(0, 4) - 2
self.vx = random.randint(0, 4) - 2

#This function will update the ball's position
def move(self):
#Add the velocity value to the position
self.x += self.vx
self.y += self.vy

#If the ball is outside the bounds put it inside and multiply the velocity to -1 to change the ball's direction
if self.x - self.radius < 0:
self.vx *= -1
elif self.x + self.radius > SCREEN_WIDTH:
self.vx *= -1
if self.y - self.radius < 0:
self.vy *= -1
elif self.y + self.radius > SCREEN_HEIGHT:
self.vy *= -1

#This class represents the green ball that makes the player loose points when he touches it
#It is similar to the GreenBall class, but it's colour is red and the velocity values are different
class RedBall(Ball):
def __init__(self, x, y, radius, color, screen):
Ball.__init__(self, x, y, radius, color, screen)
self.vy = random.randint(0, 6) - 3
self.vx = random.randint(0, 6) - 3
while self.vy == 0 or self.vx == 0:
self.vy = random.randint(0, 6) - 3
self.vx = random.randint(0, 6) - 3

def move(self):
#Add the velocity value to the position
self.x += self.vx
self.y += self.vy

#If the ball is outside the bounds put it inside and multiply the velocity to -1 to change the ball's direction
if self.x - self.radius < 0:
self.vx *= -1
elif self.x + self.radius > SCREEN_WIDTH:
self.vx *= -1
if self.y - self.radius < 0:
self.vy *= -1
elif self.y + self.radius > SCREEN_HEIGHT:
self.vy *= -1

#The next two lines initiate the game and set the window size by the values we defined on the variables SCREEN_HEIGHT and SCREEN_WIDTH
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
#The next variable represents if the user wants to quit the game (when the value is True) or not (when the value is False)
#Since we want the game to run we start it with as False
done = False
#The score variable will store the player's current score
score = 0

#Set the font and size that will be used
myfont = pygame.font.SysFont("monospace", 15)

#Create a clock value that allows us to set the FPS value we want
clock = pygame.time.Clock()

#Create a ball of each of the classes that are implemented
ball1 = PlayerBall(100, 100, 20, (0, 0, 0), screen)
ball2 = GreenBall(200, 200, 5, (0, 255, 0), screen)
ball3 = RedBall(250, 300, 20, (255, 0, 0), screen)

#While the user doesn't quit
while not done:
#Listen to all events that happen
for event in pygame.event.get():
#If it's a quit event then set done to true so the game will finish
if event.type == pygame.QUIT:
done = True

#If the players didnt' win or loose yet then keep the balls updating
if score > -1000 and score < 1000:
#Listen for keys pressed
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
ball1.move("UP")
if pressed[pygame.K_DOWN]:
ball1.move("DOWN")
if pressed[pygame.K_LEFT]:
ball1.move("LEFT")
if pressed[pygame.K_RIGHT]:
ball1.move("RIGHT")

#Paint the screen white
screen.fill((255, 255, 255))

#Set the label value to be black and write the actual score
label = myfont.render("SCORE: " + str(score), 1, (0,0,0))
#Print that label in the screen
screen.blit(label, (10, SCREEN_HEIGHT - 20))

#Call the move functions for the red and green ball to update their position
ball2.move()
ball3.move()
#Update the score based on the balls that are touching the player's ball
score += ball1.check_contact(ball2, ball3)

#Draw all the balls by calling their draw function
ball2.draw()
ball3.draw()
ball1.draw()

#Update the cooldowns for touching the red and green ball
if ball1.green_cooldown > 0:
ball1.green_cooldown -= 1
if ball1.red_cooldown > 0:
ball1.red_cooldown -= 1
#if the players won or lost then stop updating the balls and add a message to the screen
else:
#Create a new font, bigger than before
myfont = pygame.font.SysFont("monospace", 50)
#if the score is -1000 then the player lost and we create the "YOU LOSE!" label and add it to the screen
if score == -1000:
label = myfont.render("YOU LOSE!", 1, (0,0,0))
screen.blit(label, (0,0))
#if the score is 1000 then the player won and we create the "YOU WIN!" label and add it to the screen
if score == 1000:
label = myfont.render("YOU WIN!", 1, (0,0,0))
screen.blit(label, (0,0))

#Update the screen
pygame.display.flip()
#Set the FPS value to 60
clock.tick(60)

```