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

"""
   一个创意打砖块游戏,用Python的pygame模块,这个版本实现了道具的设计。
   dead死亡道具,骷髅头,skeleton.png,不小心接到它后ball.lives减一,出现机率大
   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.group.add(self)
        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):
    """显示封面"""
    cover_image = pygame.image.load(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     # 砖块两边的到屏幕边缘的距离
    up_pad = 50                                    # 顶端距离
    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("埃及爆破砖_道具的设计")
    
    ball_image = pygame.image.load(ball_image).convert_alpha()
    brick_image = pygame.image.load(brick_image).convert_alpha()
    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
    prop_images['dead'] = pygame.image.load("resources/skeleton.png").convert_alpha()
    prop_images['speedup'] = pygame.image.load("resources/speedup.png").convert_alpha()
    prop_images['slowdown'] = pygame.image.load("resources/slowdown.png").convert_alpha()
    
    
    
    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("游戏结束!")
            










    

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