## ~ Game Design

### Challenge 4

Nearly there - You have added a score variable and add a smaller GREEN ball (ball2) (inherits from the ball class) that randomly moves about the screen. You've also created the functionality that allows for when ball1 touches the green ball, the score increments by +10. The code below creates a red ball (ball 3). When ball 1 touches the red ball, the score decrements by -10.

### CHALLENGE :

1. Copy and paste the code below

2. Extend the program to do the following:

>>Add a "Game over" feature. When the score reaches 1000 (You Win) or when the score reaches -1000 (You lose)

### 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

#Listen for keys pressed
pressed = pygame.key.get_pressed()
#Call the function to update the ball's position based on the keys that are being 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

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

```