And that's it! We're here. You now just need to add the "Game over" feature which is shown in the code below
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:
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.radius = radius self.screen = screen self.color = color #The draw function will be responsible for drawing the ball in the screen def draw(self): pygame.draw.circle(screen, self.color, [self.x, self.y], self.radius) #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: self.x = self.radius elif self.x + self.radius > SCREEN_WIDTH: self.x = SCREEN_WIDTH - self.radius if self.y - self.radius < 0: self.y = self.radius elif self.y + self.radius > SCREEN_HEIGHT: self.y = SCREEN_HEIGHT - self.radius #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 return to_return #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.x = self.radius self.vx *= -1 elif self.x + self.radius > SCREEN_WIDTH: self.x = SCREEN_WIDTH - self.radius self.vx *= -1 if self.y - self.radius < 0: self.y = self.radius self.vy *= -1 elif self.y + self.radius > SCREEN_HEIGHT: self.y = SCREEN_HEIGHT - self.radius 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.x = self.radius self.vx *= -1 elif self.x + self.radius > SCREEN_WIDTH: self.x = SCREEN_WIDTH - self.radius self.vx *= -1 if self.y - self.radius < 0: self.y = self.radius self.vy *= -1 elif self.y + self.radius > SCREEN_HEIGHT: self.y = SCREEN_HEIGHT - self.radius 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)