### Python创意打砖块游戏埃及爆破砖

```"""
一个创意打砖块游戏,用Python的pygame模块,这个版本实现了道具的设计。
life生命道具，15.png 核桃图形，接到后ball.lives加一
speedup加速道具，speedup.png，接到它后球的速度翻倍
slowdown减速道具，slowdown.png，接到它后球的速度减倍。

"""

import time
import pygame
from pygame.locals import *
from random import choice,randint
from brick import *                        # 导入Brick类
from prop import *                         # 导入Prop类
from board import *                        # 导入Board类

class Ball(pygame.sprite.Sprite):
"""弹球类"""
def __init__(self,image,screen,board):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect()
self.screen = screen
self.screen_width = screen.get_width()
self.screen_height = screen.get_height()
self.board = board           # 球能访问board
self.dx = 0
self.dy = 0
self.shoot_flag = 0
self.lives = 5                       # 球的数量

def shoot(self):
if self.shoot_flag == 0:             # 只有小球呆在拦板上才可以发射，否则在空中也能发射
self.dx = choice([-10,-9,-8,-7,-6,-5,5,6,7,8,9,10])
self.dy = choice([-10,-9,-8,-7,-6,-5])
self.shoot_flag = 1

def update(self):
if self.shoot_flag == 0 :
self.rect.bottom =  self.board.rect.top
self.rect.centerx = self.board.rect.centerx
else:
self.rect.move_ip(self.dx,self.dy)
if self.rect.top > self.screen_height + 200: # 弹球丢失，重新开始或结束游戏
self.lives -= 1                         # 数量减去1
self.shoot_flag = 0                     # 发射标志
self.board.lost_ball()                  # 变短拦板
pygame.display.set_caption("埃及爆破砖：" + str(self.lives))
if self.rect.left <= 0 or self.rect.right >= self.screen_width: # 碰到左右边缘反弹
self.dx = -self.dx
if abs(self.dy) < 0.1 :                       # 特殊情况可能dy为0，这时球永远不会下来
self.dy = randint(1,2)
if self.rect.top <= 0:                     # 碰到上边缘反弹
self.dy = -self.dy

def draw(self):
self.screen.blit(self.image,self.rect)

class Explosion(pygame.sprite.Sprite):
"""爆炸类"""
def __init__(self,images,position,group,screen):
pygame.sprite.Sprite.__init__(self)
self.images = images
self.index = 0
self.amounts = len(images)
self.interval = 0.1               # 造型切换时间(秒)
self.begin_time = time.time()     # 起始时间
self.image = self.images[0]       # 最初的图形对象
self.rect = self.image.get_rect() # 矩形对象
self.rect.center = position       # 爆炸坐标
self.group = group
self.screen = screen
def update(self):
if self.index < self.amounts:
if time.time() - self.begin_time > self.interval: # 超时换造型
oldcenter = self.rect.center
self.image = self.images[self.index]
self.index = self.index + 1
self.rect = self.image.get_rect()
self.rect.center = oldcenter
self.begin_time = time.time()
else:
self.group.remove(self)

def display_cover(cover_image):
"""显示封面"""
clock = pygame.time.Clock()
exit_game = False
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
exit_game = True
break
if event.type == KEYDOWN:
if event.key == K_SPACE:
running = False
break
screen.blit(cover_image,(0,0))
pygame.display.update()
clock.tick(10)
return exit_game

def start_level(level_index):
"""生成砖块，启动这一关"""
rows,cols = level_design[level_index]
all_bricks_width = cols * 100 + (cols-1) * 20  # 所有砖块的宽度
left_pad = (width - all_bricks_width) // 2     # 砖块两边的到屏幕边缘的距离
for r in range(rows):                          # 摆砖块
for c in range(cols):
x = left_pad + c * 120
y = up_pad +r * 60
Brick(brick_image,(x,y),brick_group)

exit_game = False
while len(brick_group) > 0 and exit_game ==False:
for event in pygame.event.get():
if event.type == QUIT:
exit_game = True
break
if event.type == MOUSEMOTION:
board.update(event.pos)
if event.type == MOUSEBUTTONUP:
ball.shoot()
print(ball.shoot_flag)

if ball.lives == 0:
exit_game = True
break
ball.update()
brick_group.update()
explosion_group.update()
prop_group.update()

collision_check()            #这个函数是检测所有对象之间的碰撞检测

screen.fill((0,0,0))
board.draw()
ball.draw()
brick_group.draw(screen)
explosion_group.draw(screen)
prop_group.draw(screen)
pygame.display.update()
clock.tick(60)
print("退出本关")
"关卡完后，弹球归位"
explosion_group.empty()       # 爆炸组清空
prop_group.empty()            # 道具组清空
ball.shoot_flag = 0
return exit_game

def collision_check():

"小球和砖块组的碰撞"
b =  pygame.sprite.spritecollideany(ball, brick_group)    # 球和砖块组的碰撞，返回碰到的砖块
if b!=None:
position = b.rect.center                              # 移除砖块前记录坐标
brick_group.remove(b)
Explosion(explosion_images,b.rect.center,explosion_group,screen)
ball.dy = -ball.dy                                    # 球的垂直速度反转
"以一定的机率生成一个道具"
if randint(1,2) ==1 :                               #生成一个道具
Prop(prop_images,position,prop_group,screen)
print("生成了一个道具")

"小球和拦板在碰撞"
t = pygame.sprite.collide_rect(ball,board)  # 球和拦板的碰撞
if t :
ball.dy = -ball.dy
ball.dx = ball.dx + randint(-3,3)       # 不确定的左右速度改变
"拦板和道具组的碰撞"
p =  pygame.sprite.spritecollideany(board, prop_group)   # 返回碰到的道具
if p!=None:
name = p.key                          # 道具的名字，就是它几个surface对应的key
prop_group.remove(p)                  # 拦板碰到一个道具，马上移除它
if name == 'life':                    # 如果收到生命道具，生命数量加1，拦板变长
ball.lives +=1
board.get_prop()                  # 变长
pygame.display.set_caption("埃及爆破砖：" + str(ball.lives))
elif name == 'dead':                  # 收到死亡道具内，骷髅头，生命数量减1
ball.lives -=1
pygame.display.set_caption("埃及爆破砖：" + str(ball.lives))
elif name =='speedup':                # 加速道具
ball.dx = 2 * ball.dx
ball.dy = 2 * ball.dy
elif name == 'slowdown':              # 减速道具
ball.dx = 0.5 * ball.dx
ball.dy = 0.5 * ball.dy

def wait_press_any_key():

clock = pygame.time.Clock()
exit_game = False
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
exit_game = True
break
if event.type == KEYDOWN:
running = False
break
screen.blit(level_images[level_index],(0,0))
pygame.display.update()
clock.tick(10)
return exit_game

if __name__ == "__main__":

width,height = 960,720
ball_image = "resources/15.png"              # 弹球图
brick_image = "resources/brick.png"          # 砖图
cover_image = "resources/cover.png"          # 封面图
explosion_images = ["resources/" + str(i) + ".png" for i in range(7,13)] # 爆炸序列图
board_images = ["resources/" + str(i) + ".png" for i in range(5,0,-1)]   # 拦板序列图，从长到短
level_images = ["resources/" + str(i) + ".png" for i in range(17,22)]    # 关卡完后显示的图
level_design = [(2,4),(4,4),(6,6),(8,6),(9,8)]                  # 记录每关的砖块行列数
level_amounts = len(level_design)

pygame.init()
screen = pygame.display.set_mode((width,height))
pygame.display.set_caption("埃及爆破砖_道具的设计")

board_images = [pygame.image.load(image).convert_alpha() for image in board_images]
level_images = [pygame.image.load(image).convert_alpha() for image in level_images]
explosion_images = [pygame.image.load(image).convert_alpha() for image in explosion_images]

prop_images = {}
prop_images['life'] = ball_image

exit_game = display_cover(cover_image)                  # 按空格键开始游戏
if exit_game :
pygame.quit()
else:
brick_group = pygame.sprite.Group()     # 砖块组
explosion_group = pygame.sprite.Group() # 爆炸组
prop_group = pygame.sprite.Group()      # 道具组

board= Board(board_images,screen)
ball = Ball(ball_image,screen,board)
exit_game1 = False
exit_game2 = False
clock = pygame.time.Clock()
level_index = 0
while level_index < level_amounts:      # 遍历关卡
exit_game1 = start_level(level_index)
if exit_game1 != True:
exit_game2 = wait_press_any_key() # 没有在游戏中按关闭按钮，那就等待按任意键开始下一关
level_index += 1
if exit_game2:break
else:
break

if exit_game1 == False and exit_game2 == False:
"以下是显示结束时的画面"
running = True
while running:
event = pygame.event.poll()
if event.type in ( QUIT,KEYDOWN,MOUSEBUTTONDOWN ):
running = False
break
screen.blit(level_images[level_index-1],(0,0))
pygame.display.update()
clock.tick(10)
pygame.quit()
print("游戏结束！")

```