Project 1659

by Maja M

Description

""" File: brickbreaker.py ---------------- Brick breaker game. Paddle changes color to the current color of the ball every time it is hit. The game restarts 5 second after defeat or victory. """ import tkinter import time import random import colorsys import time # How big is the playing area? CANVAS_WIDTH = 600 # Width of drawing canvas in pixels CANVAS_HEIGHT = 800 # Height of drawing canvas in pixels # Constants for the bricks N_ROWS = 10 # How many rows of bricks are there? N_COLS = 10 # How many columns of bricks are there? SPACING = 5 # How much space is there between each brick? BRICK_START_Y = 50 # The y coordinate of the top-most brick BRICK_HEIGHT = 20 # How many pixels high is each brick BRICK_WIDTH = (CANVAS_WIDTH - (N_COLS + 1) * SPACING) / N_COLS # Constants for the ball and paddle BALL_SIZE = 25 PADDLE_Y = CANVAS_HEIGHT - 40 PADDLE_WIDTH = 80 LIVES = 3 BRICK_TAG = "brick" def main(): # create canvas canvas = make_canvas(CANVAS_WIDTH, CANVAS_HEIGHT, 'Brick Breaker') while True: play_game(canvas) time.sleep(5) # Pause (sleep) canvas.mainloop() def play_game(canvas): """ A single game of brickbreaker. """ canvas.delete("all") # create bricks for row in range(N_ROWS): for col in range(N_COLS): draw_brick(canvas, row, col) # create ball ball = make_ball(canvas) change_x = 10 change_y = 10 # create paddle paddle = canvas.create_rectangle(0, PADDLE_Y, PADDLE_WIDTH, PADDLE_Y + BRICK_HEIGHT, fill='white', width=1) # set background canvas.configure(bg='black') death_count = 0 any_bricks_left = True while death_count < LIVES and any_bricks_left: give_another_chance = False # paddle movement paddle_x = min(canvas.winfo_pointerx(), CANVAS_WIDTH - PADDLE_WIDTH) canvas.moveto(paddle, paddle_x, PADDLE_Y) # ball movement canvas.move(ball, change_x, change_y) if hit_top_wall(canvas, ball): change_y *= -1 if hit_right_wall(canvas, ball) or hit_left_wall(canvas, ball): change_x *= -1 if hit_paddle(canvas, ball, paddle): change_x *= -1 change_color(canvas, paddle) if hit_brick(canvas, ball, paddle): brick_count = len(canvas.find_withtag(BRICK_TAG)) any_bricks_left = brick_count > 0 change_y *= -1 if hit_bottom_wall(canvas, ball): canvas.delete(ball) death_count += 1 give_another_chance = death_count < LIVES if give_another_chance: ball = make_ball(canvas) # pause change_color(canvas, ball) canvas.update() time.sleep(1 if give_another_chance else 1 / 50.) if any_bricks_left: canvas.create_text(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, text="GAME OVER", fill='white', font=("Game Commands", 40, "bold")) else: canvas.create_text(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, text="CONGRATULATIONS", fill=current_ball_color(), font=("Game Commands", 25, "bold")) canvas.update() def current_ball_color(): """ Returns current ball color in the RGB format. """ return hue_to_rgb_string(time.time() / 5) def change_color(canvas, ball): """ Sets the color of the ball to the current """ color = current_ball_color() canvas.itemconfig(ball, fill=color, outline=color) def make_ball(canvas): """ Creates the ball. """ x = (CANVAS_WIDTH - BALL_SIZE) / 2 y = (CANVAS_HEIGHT - BALL_SIZE) / 2 return canvas.create_oval(x, y, x + BALL_SIZE, y + BALL_SIZE, fill='black', width=0) def draw_brick(canvas, row, col): """ Draws the bricks. """ x = col * (BRICK_WIDTH + SPACING) + 7 y = row * (BRICK_HEIGHT + SPACING) + 30 color = hue_to_rgb_string((row * 10 + col) / 100) brick = canvas.create_rectangle(x, y, x + BRICK_WIDTH, y + BRICK_HEIGHT, fill=color, outline=color, tags=BRICK_TAG) return brick def hue_to_rgb_string(hue): """ Changes the color from HSV format to RGB. Returns color in the RGB format. """ return "#%02X%02X%02X" % tuple(map(lambda x: int(255 * x) % 255, colorsys.hsv_to_rgb(hue, 0.7, 0.9))) def get_top_y(canvas, ball): """ This friendly method returns the y coordinate of the top of an object. Recall that canvas.coords(object) returns a list of the object bounding box: [x_1, y_1, x_2, y_2]. The element at index 1 is the top-y """ return canvas.coords(ball)[1] def get_left_x(canvas, ball): """ This friendly method returns the x coordinate of the left of an object. Recall that canvas.coords(object) returns a list of the object bounding box: [x_1, y_1, x_2, y_2]. The element at index 0 is the left-x """ return canvas.coords(ball)[0] def hit_paddle(canvas, ball, paddle): """ Checks if the paddle is colliding with anything. """ paddle_coords = canvas.coords(paddle) x1 = paddle_coords[0] y1 = paddle_coords[1] x2 = paddle_coords[2] y2 = paddle_coords[3] results = canvas.find_overlapping(x1, y1, x2, y2) return len(results) > 1 def hit_left_wall(canvas, ball): return get_left_x(canvas, ball) <= 0 def hit_top_wall(canvas, ball): return get_top_y(canvas, ball) <= 0 def hit_right_wall(canvas, ball): return get_right_x(canvas, ball) >= CANVAS_WIDTH def hit_bottom_wall(canvas, ball): return get_bottom_y(canvas, ball) >= CANVAS_HEIGHT def get_right_x(canvas, ball): return canvas.coords(ball)[2] def get_bottom_y(canvas, ball): return canvas.coords(ball)[3] def hit_brick(canvas, ball, paddle): """ Checks if the ball is colliding with an object. If it does collide and the object is neither the ball nor the paddle, deletes it. """ ball_coords = canvas.coords(ball) x_1 = ball_coords[0] y_1 = ball_coords[1] x_2 = ball_coords[2] y_2 = ball_coords[3] colliding_list = canvas.find_overlapping(x_1, y_1, x_2, y_2) if len(colliding_list) > 0: for obj in colliding_list: if obj != ball and obj != paddle: canvas.delete(obj) return len(colliding_list) > 1 def make_canvas(width, height, title): """ DO NOT MODIFY Creates and returns a drawing canvas of the given int size with a blue border, ready for drawing. """ top = tkinter.Tk() top.minsize(width=width, height=height) top.title(title) canvas = tkinter.Canvas(top, width=width + 1, height=height + 1) canvas.pack() return canvas if __name__ == '__main__': main() Brick breaker game. Paddle changes color to the current color of the ball every time it is hit. The game restarts 5 second after defeat or victory.