"""
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.