Python+pyGame 打砖块游戏

注:以下程序为本人原创,写的不好,若有好的建议,望留言告知。而若能帮助一二访客,幸甚!


最近搞“科研”搞的蛋都碎了。。。

思吾之理想是将计算机玩弄于股掌之上(将计算机组成原理、操作系统、程序运行机理、程序设计语言、计算机网络、算法数据结构学扎实了…呃,理想而已,至今所以这些选项都学得不达标。。),而如今却为了毕业在跟着一群数学家“搞科研”,而实验又做来做去都那个样,一点效果也没有,真是蛋疼啊。

昨晚照着Andre LaMothe大师《Windows游戏编程大师技巧》一书第一章示例程序,略作修改做了一个打砖块游戏以学习Win32 程序组织技巧,略有所得。今晚决定尝试使用Python + pyGame 实现一个类似的程序,以学习Python,聊以解闷。

当然实现一个几乎相同的要简单些,但为了更有成就感,决定功能上略作修改:昨晚实现的程序,按照书上的实现,当小球落地没接住,会减100分,但不会死亡,今晚决定实现一个更普遍的打砖块,即小球落地,会生命减1,生命没了就Game over。

1.功能划分

俗话说大事化小,小事化无;又曰天下难事,必作于易。

虽然写个打砖块并非太难的事,但将它分解开来,分解的足够简单还是有必要的。

现将一个打砖块的主要功能分解如下:

1)实现一个小球在屏幕上移动

2)碰到边缘要能够反弹

3)挡板绘制和移动

4)砖块的绘制

5)游戏流程和控制逻辑

6)绘制文字显示游戏信息

7)加个背景音乐

这几个功能应该都是在一定时间内能够实现的简单功能,而只要将他们合理的组合起来就是一个完整的打砖块游戏了~

2. 小球的绘制和移动

画个小球?怎么画来?忘了……

好吧,把古老的pyGame 做的 Hello World 找出来看看吧,看来积累还是很重要的,毕竟一个打砖块最终划分成了若干个Hello world 嘛~~

连上注释30几行代码,先做出一个游戏界面框架来:

'''
功能:使用pyGame实现一个简单的打砖块游戏
Created on Nov 30, 2012
@author: liury_lab
'''

import pygame, sys, time    #@UnusedImport
from pygame.locals import * #@UnusedWildImport

# 一些关于宽度和高度的常量定义
WINDOWWIDTH = 640
WINDOWHEIGHT = 480

# 一些颜色常量定义
BACKGROUNDCOLOR = (0, 0, 0)

# 游戏的初始化
pygame.init()
mainClock = pygame.time.Clock()

windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('打砖块')

# 游戏主循环
while True:
    # 事件监听
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()
    
    windowSurface.fill(BACKGROUNDCOLOR)
    
    pygame.display.update()
    mainClock.tick(30)
    


下面画个会动的小球吧:

# 游戏主循环
while True:
    # 事件监听
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()
    
    if game_state == GAME_STATE_INIT:
        # 初始化游戏
        ball_x  = random.randint(8, WINDOW_WIDTH-8)
        ball_y  = BALL_START_Y
        ball_dx = random.randint(-4, 4)
        ball_dy = random.randint( 6, 8)
        
        game_state = GAME_STATE_START_LEVEL
    elif game_state == GAME_STATE_START_LEVEL:
        # 新的一关
        game_state = GAME_STATE_RUN
    elif game_state == GAME_STATE_RUN:
        # 游戏运行
        ball_x += ball_dx;
        ball_y += ball_dy;
        windowSurface.fill(BACKGROUND_COLOR)
        pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), BALL_SIZE, 0)
    elif game_state == GAME_STATE_SHUTDOWN:
        game_state = GAME_STATE_EXIT
    
    pygame.display.update()
    mainClock.tick(30)



1)会动的小球画好了,但很快它就跑到屏幕外头再也不会来了…

2)我不得不承认小球跑的太快,我无法抓图抓住它,只好做了个不会动的小球截了个图…

3)呃,没按计划办事,游戏的流程在这里就写好了,当然,有昨晚大师的Win32 程序做基础,这个流程还是很容易写的

3. 碰撞检测

小球一出来就开始跑,一会儿就不见了。这一步要让它碰到边界就反弹回去。

这个速度的改变有点类似于光的反射。

只需要添加下面几行代码就好了:

    elif game_state == GAME_STATE_RUN:
        # 游戏运行
        ball_x += ball_dx;
        ball_y += ball_dy;
        
        if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
            ball_dx = -ball_dx
            ball_x  += ball_dx;
        elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
            ball_dy = -ball_dy
            ball_y  += ball_dy

现在球不会跑出屏幕外头了,可以很轻松地截图了,但和前面的几乎一模一样,就不贴了吧~

4. 挡板绘制和移动

然后就是实现一个能够根据玩家输入移动的挡板,来阻挡小球。

当然上面的代码需要修改,若小球超出了下边界而没有被挡板挡住,则损失一条生命,此是后话,此处值实现绘制和移动,先不检测与球的碰撞。

# 游戏主循环
while True:
    # 事件监听
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()
        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                paddle_move_left = True
            if event.key == K_RIGHT:
                paddle_move_right = True
        if event.type == KEYUP:
            if event.key == K_LEFT:
                paddle_move_left = False
            if event.key == K_RIGHT:
                paddle_move_right = False
    # 游戏控制流程           
    if game_state == GAME_STATE_INIT:
        # 初始化游戏
        ball_x  = random.randint(8, WINDOW_WIDTH-8)
        ball_y  = BALL_START_Y
        ball_dx = random.randint(-4, 4)
        ball_dy = random.randint( 6, 8)
        
        paddle['rect'].left = PADDLE_START_X
        paddle['rect'].top  = PADDLE_START_Y
        
        paddle_move_left  = False
        paddle_move_right = False
        
        game_state = GAME_STATE_START_LEVEL
    elif game_state == GAME_STATE_START_LEVEL:
        # 新的一关
        game_state = GAME_STATE_RUN
    elif game_state == GAME_STATE_RUN:
        # 游戏运行
        
        # 球的运动
        ball_x += ball_dx;
        ball_y += ball_dy;
        
        if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
            ball_dx = -ball_dx
            ball_x  += ball_dx;
        elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
            ball_dy = -ball_dy
            ball_y  += ball_dy
            
        # 挡板的运动
        if paddle_move_left:
            paddle['rect'].left -= 8
            if paddle['rect'].left < 0:
                paddle['rect'].left = 0
        if paddle_move_right:
            paddle['rect'].left += 8
            if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
                paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
        
        # 绘制过程
        windowSurface.fill(BACKGROUND_COLOR)
        pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
        pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), BALL_SIZE, 0)
    elif game_state == GAME_STATE_SHUTDOWN:
        game_state = GAME_STATE_EXIT
    
    pygame.display.update()
    mainClock.tick(30)

5. 砖块的绘制

首先要有个数组记录砖块是否已经被打掉了,然后把未被打掉的绘制在窗口上部

初始化砖块二维数组:

# 初始化砖块数组
def InitBlocks():
    blocks = [[1] * NUM_BLOCK_COLUMNS] * NUM_BLOCK_ROWS
    return blocks

砖块的绘制:

    elif game_state == GAME_STATE_START_LEVEL:
        # 新的一关
        blocks = InitBlocks()
        game_state = GAME_STATE_RUN
    elif game_state == GAME_STATE_RUN:
        # 游戏运行
        
        # 球的运动
        ball_x += ball_dx;
        ball_y += ball_dy;
        
        if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
            ball_dx = -ball_dx
            ball_x  += ball_dx;
        elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
            ball_dy = -ball_dy
            ball_y  += ball_dy
            
        # 挡板的运动
        if paddle_move_left:
            paddle['rect'].left -= 8
            if paddle['rect'].left < 0:
                paddle['rect'].left = 0
        if paddle_move_right:
            paddle['rect'].left += 8
            if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
                paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
        
        # 绘制过程
        windowSurface.fill(BACKGROUND_COLOR)
        # 绘制挡板
        pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
        # 绘制小球
        pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), 
                           BALL_SIZE, 0)
        # 绘制砖块
        cur_x = BLOCK_ORIGIN_X
        cur_y = BLOCK_ORIGIN_Y
        for row in range(NUM_BLOCK_ROWS):
            cur_x = BLOCK_ORIGIN_X
            for col in range(NUM_BLOCK_COLUMNS):
                print(blocks[row][col])
                if (blocks[row][col] == 1):
                    pygame.draw.rect(windowSurface, BLOCK_COLOR, 
                                     (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
                cur_x += BLOCK_X_GAP
            cur_y += BLOCK_Y_GAP


随便写了个RGB,好鲜亮的砖块颜色,很合我意,最起码比昨晚蒙的那个Win32 版的好……

6. 游戏流程和控制逻辑

边角的工作都做完了,只差游戏的逻辑了,正所谓万事俱备,只欠东风。

1)把砖块打破

2)被挡板挡住才返回,落没挡住则要减少一条生命

3)生命用完了则Game Over

4)砖块打完了要进入下一关或宣告胜利

    

    elif game_state == GAME_STATE_RUN:
        # 游戏运行
        
        # 球的运动
        ball_x += ball_dx;
        ball_y += ball_dy;
        
        if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
            ball_dx = -ball_dx
            ball_x  += ball_dx;
        elif ball_y < BALL_SIZE:
            ball_dy = -ball_dy
            ball_y  += ball_dy
        elif ball_y > WINDOW_HEIGHT-BALL_SIZE:
            if life_left == 0:
                game_state = GAME_STATE_GAMEOVER
            else:
                life_left -= 1
                # 初始化游戏
                ball_x  = paddle['rect'].left + PADDLE_WIDTH // 2
                ball_y  = BALL_START_Y
                ball_dx = random.randint(-4, 5)
                ball_dy = random.randint( 6, 9)
            
        # 检测球是否与挡板碰撞
        if ball_y > WINDOW_HEIGHT // 2:
            if (ball_x+BALL_SIZE >= paddle['rect'].left and \
                ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
                ball_y+BALL_SIZE >= paddle['rect'].top and \
                ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
                ball_dy = - ball_dy
                ball_y += ball_dy
                if paddle_move_left:
                    ball_dx -= random.randint(0, 2)
                elif paddle_move_right:
                    ball_dx += random.randint(0, 2)
                else:
                    ball_dx += random.randint(-1, 2)
                    
        # 检测球是否与砖块碰撞
        cur_x = BLOCK_ORIGIN_X
        cur_y = BLOCK_ORIGIN_Y
        for row in range(NUM_BLOCK_ROWS):
            cur_x = BLOCK_ORIGIN_X
            for col in range(NUM_BLOCK_COLUMNS):
                if blocks[row][col] != 0:
                    if (ball_x+BALL_SIZE >= cur_x and \
                        ball_x-BALL_SIZE <= cur_x+BLOCK_WIDTH and \
                        ball_y+BALL_SIZE >= cur_y and \
                        ball_y-BALL_SIZE <= cur_y+BLOCK_HEIGHT):
                        blocks[row][col] = 0
                        blocks_hit += 1
                        ball_dy = -ball_dy
                        ball_dx += random.randint(-1, 2)
                        score += 5 * (level + abs(ball_dx))
                cur_x += BLOCK_X_GAP
            cur_y += BLOCK_Y_GAP
            
        if blocks_hit == NUM_BLOCK_ROWS * NUM_BLOCK_COLUMNS:
            level += 1
            game_state = GAME_STATE_START_LEVEL
            
        # 挡板的运动
        if paddle_move_left:
            paddle['rect'].left -= 8
            if paddle['rect'].left < 0:
                paddle['rect'].left = 0
        if paddle_move_right:
            paddle['rect'].left += 8
            if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
                paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
        
        # 绘制过程
        windowSurface.fill(BACKGROUND_COLOR)
        # 绘制挡板
        pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
        # 绘制小球
        pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), 
                           BALL_SIZE, 0)
        # 绘制砖块
        cur_x = BLOCK_ORIGIN_X
        cur_y = BLOCK_ORIGIN_Y
        for row in range(NUM_BLOCK_ROWS):
            cur_x = BLOCK_ORIGIN_X
            for col in range(NUM_BLOCK_COLUMNS):
                if blocks[row][col] != 0:
                    pygame.draw.rect(windowSurface, BLOCK_COLOR, 
                                     (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
                cur_x += BLOCK_X_GAP
            cur_y += BLOCK_Y_GAP
    elif game_state == GAME_STATE_GAMEOVER:
        continue
    elif game_state == GAME_STATE_SHUTDOWN:
        game_state = GAME_STATE_EXIT
    
    pygame.display.update()
    mainClock.tick(30)


7. 绘制文字显示游戏信息

绘制函数:
# 显示文字
def DrawText(text, font, surface, x, y):
    text_obj = font.render(text, 1, TEXT_COLOR)
    text_rect = text_obj.get_rect()
    text_rect.topleft = (x, y)
    surface.blit(text_obj, text_rect)


合理计算分数,并设置过关:
比如每过一关加1000分,打完所有砖块则进入下一关。
左下角显示游戏信息,如关卡、分数、生命等,游戏结束显示Game Over信息

# 游戏主循环
while True:
    # 事件监听
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()
        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                paddle_move_left = True
            if event.key == K_RIGHT:
                paddle_move_right = True
        if event.type == KEYUP:
            if event.key == K_LEFT:
                paddle_move_left = False
            if event.key == K_RIGHT:
                paddle_move_right = False
    # 游戏控制流程           
    if game_state == GAME_STATE_INIT:
        # 初始化游戏
        ball_x  = random.randint(8, WINDOW_WIDTH-8)
        ball_y  = BALL_START_Y
        ball_dx = random.randint(-3, 4)
        ball_dy = random.randint( 5, 8)
        
        paddle['rect'].left = PADDLE_START_X
        paddle['rect'].top  = PADDLE_START_Y
        
        paddle_move_left  = False
        paddle_move_right = False
        
        life_left   = TOTAL_LIFE
        game_over   = False
        blocks_hit  = 0
        score       = 0
        level       = 1
        game_state  = GAME_STATE_START_LEVEL
    elif game_state == GAME_STATE_START_LEVEL:
        # 新的一关
        blocks = InitBlocks()
        game_state = GAME_STATE_RUN
    elif game_state == GAME_STATE_RUN:
        # 游戏运行
        
        # 球的运动
        ball_x += ball_dx;
        ball_y += ball_dy;
        
        if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
            ball_dx = -ball_dx
            ball_x  += ball_dx;
        elif ball_y < BALL_SIZE:
            ball_dy = -ball_dy
            ball_y  += ball_dy
        elif ball_y > WINDOW_HEIGHT-BALL_SIZE:
            if life_left == 0:
                game_state = GAME_STATE_GAMEOVER
            else:
                life_left -= 1
                # 初始化游戏
                ball_x  = paddle['rect'].left + PADDLE_WIDTH // 2
                ball_y  = BALL_START_Y
                ball_dx = random.randint(-4, 5)
                ball_dy = random.randint( 6, 9)
            
        # 检测球是否与挡板碰撞
        if ball_y > WINDOW_HEIGHT // 2:
            if (ball_x+BALL_SIZE >= paddle['rect'].left and \
                ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
                ball_y+BALL_SIZE >= paddle['rect'].top and \
                ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
                ball_dy = - ball_dy
                ball_y += ball_dy
                if paddle_move_left:
                    ball_dx -= random.randint(0, 2)
                elif paddle_move_right:
                    ball_dx += random.randint(0, 2)
                else:
                    ball_dx += random.randint(-1, 2)
                    
        # 检测球是否与砖块碰撞
        cur_x = BLOCK_ORIGIN_X
        cur_y = BLOCK_ORIGIN_Y
        for row in range(NUM_BLOCK_ROWS):
            cur_x = BLOCK_ORIGIN_X
            for col in range(NUM_BLOCK_COLUMNS):
                if blocks[row][col] != 0:
                    if (ball_x+BALL_SIZE >= cur_x and \
                        ball_x-BALL_SIZE <= cur_x+BLOCK_WIDTH and \
                        ball_y+BALL_SIZE >= cur_y and \
                        ball_y-BALL_SIZE <= cur_y+BLOCK_HEIGHT):
                        blocks[row][col] = 0
                        blocks_hit += 1
                        ball_dy = -ball_dy
                        ball_dx += random.randint(-1, 2)
                        score += 5 * (level + abs(ball_dx))
                cur_x += BLOCK_X_GAP
            cur_y += BLOCK_Y_GAP
            
        if blocks_hit == NUM_BLOCK_ROWS * NUM_BLOCK_COLUMNS:
            level += 1
            blocks_hit = 0
            score += 1000
            game_state = GAME_STATE_START_LEVEL
            
        # 挡板的运动
        if paddle_move_left:
            paddle['rect'].left -= 8
            if paddle['rect'].left < 0:
                paddle['rect'].left = 0
        if paddle_move_right:
            paddle['rect'].left += 8
            if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
                paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
        
        # 绘制过程
        windowSurface.fill(BACKGROUND_COLOR)
        # 绘制挡板
        pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
        # 绘制小球
        pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), 
                           BALL_SIZE, 0)
        # 绘制砖块
        cur_x = BLOCK_ORIGIN_X
        cur_y = BLOCK_ORIGIN_Y
        for row in range(NUM_BLOCK_ROWS):
            cur_x = BLOCK_ORIGIN_X
            for col in range(NUM_BLOCK_COLUMNS):
                if blocks[row][col] != 0:
                    pygame.draw.rect(windowSurface, BLOCK_COLOR, 
                                     (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
                cur_x += BLOCK_X_GAP
            cur_y += BLOCK_Y_GAP
            
        # 绘制文字描述信息
        message = 'Level: ' + str(level) + '    Life: ' + str(life_left) + '    Score: ' + str(score)
        DrawText(message, text_font, windowSurface, 8, (WINDOW_HEIGHT - 16))
    elif game_state == GAME_STATE_GAMEOVER:
        DrawText('GAME OVER', game_over_font, windowSurface, (WINDOW_WIDTH / 3), (WINDOW_HEIGHT / 3))
        DrawText('Score: ' + str(score), game_over_font, windowSurface, 
                 (WINDOW_WIDTH / 3)+20, (WINDOW_HEIGHT / 3) + 50)
    elif game_state == GAME_STATE_SHUTDOWN:
        game_state = GAME_STATE_EXIT
    
    pygame.display.update()
    mainClock.tick(25 + level*2)




8. 增加个背景音乐及GameOver声音

game_over_sound = pygame.mixer.Sound('gameover.wav')
game_hit_sound = pygame.mixer.Sound('hit.wav')
pygame.mixer.music.load('background.mp3')

开始及停止播放:

# 播放背景音乐
pygame.mixer.music.play(-1, 0.0)

pygame.mixer.music.stop()
game_over_sound.play()

9. 增加个开始画面

DrawText('pyFreakOut', game_start_font, windowSurface, 
         (WINDOW_WIDTH/3), (WINDOW_HEIGHT/3 + 50))
DrawText('Press any key to start.', game_start_font, windowSurface, 
         (WINDOW_WIDTH/3)-60, (WINDOW_HEIGHT)/3+100)
pygame.display.update()
WaitForPlayerToPressKey()


这样就会在开始时显示上面的画面等待用户按下一个键后再开始,游戏结束后问用户按下一个键重新开始,若按下Esc则退出游戏。


10. 完整代码

'''
功能:使用pyGame实现一个简单的打砖块游戏
Created on Nov 30, 2012
@author: liury_lab
'''

import pygame, sys, time, random    #@UnusedImport
from pygame.locals import *         #@UnusedWildImport

# 一些关于窗口的常量定义
WINDOW_WIDTH  = 640
WINDOW_HEIGHT = 480

# 游戏状态常量定义
GAME_STATE_INIT        = 0
GAME_STATE_START_LEVEL = 1
GAME_STATE_RUN         = 2
GAME_STATE_GAMEOVER    = 3
GAME_STATE_SHUTDOWN    = 4
GAME_STATE_EXIT        = 5

# 小球的常量定义
BALL_START_Y  = (WINDOW_HEIGHT//2)
BALL_SIZE     = 4

# 挡板的常量定义
PADDLE_START_X  = (WINDOW_WIDTH/2 - 16)
PADDLE_START_Y  = (WINDOW_HEIGHT - 32);
PADDLE_WIDTH    = 32
PADDLE_HEIGHT   = 8

# 砖块的常量定义
NUM_BLOCK_ROWS    = 6
NUM_BLOCK_COLUMNS = 8
BLOCK_WIDTH       = 64
BLOCK_HEIGHT      = 16
BLOCK_ORIGIN_X    = 8
BLOCK_ORIGIN_Y    = 8
BLOCK_X_GAP       = 80
BLOCK_Y_GAP       = 32

# 一些颜色常量定义
BACKGROUND_COLOR = (0, 0, 0)
BALL_COLOR       = (0, 0, 255)
PADDLE_COLOR     = (128, 64, 64)
BLOCK_COLOR      = (255, 128, 0)
TEXT_COLOR       = (255, 255, 255)

# 游戏的一些属性信息
TOTAL_LIFE       = 5
FPS              = 25

# 初始化砖块数组
def InitBlocks():
    #blocks = [[1] * NUM_BLOCK_COLUMNS] * NUM_BLOCK_ROWS
    blocks = []
    for i in range(NUM_BLOCK_ROWS):             #@UnusedVarialbe
        blocks.append([i+1] * NUM_BLOCK_COLUMNS)
    return blocks

# 检测小球是否与挡板或者砖块碰撞
def ProcessBall(blocks, ball_x, ball_y, paddle):
    if (ball_y > WINDOW_HEIGHT//2):
        if (ball_x+BALL_SIZE >= paddle['rect'].left and \
            ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
            ball_y+BALL_SIZE >= paddle['rect'].top and \
            ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
            return None

# 显示文字
def DrawText(text, font, surface, x, y):
    text_obj = font.render(text, 1, TEXT_COLOR)
    text_rect = text_obj.get_rect()
    text_rect.topleft = (x, y)
    surface.blit(text_obj, text_rect)

# 退出游戏
def Terminate():
    pygame.quit()
    sys.exit()
    
# 等待用户输入
def WaitForPlayerToPressKey():
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                Terminate()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    Terminate()
                return

# 游戏界面的初始化
pygame.init()
mainClock = pygame.time.Clock()
    
# 小球的位置和速度
ball_x  = 0
ball_y  = 0
ball_dx = 0
ball_dy = 0

# 挡板的运动控制
paddle_move_left  = False
paddle_move_right = False

# 挡板的位置和颜色
paddle  = {'rect' :pygame.Rect(0, 0, PADDLE_WIDTH, PADDLE_HEIGHT), 
           'color': PADDLE_COLOR}

# 游戏状态
game_state  = GAME_STATE_INIT
blocks      = []
life_left   = TOTAL_LIFE
game_over   = False
blocks_hit  = 0
score       = 0
level       = 1

game_start_font = pygame.font.SysFont(None, 48)
game_over_font  = pygame.font.SysFont(None, 48)
text_font       = pygame.font.SysFont(None, 20)

game_over_sound = pygame.mixer.Sound('gameover.wav')
game_hit_sound = pygame.mixer.Sound('hit.wav')
pygame.mixer.music.load('background.mp3')

windowSurface = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), 0, 32)
pygame.display.set_caption('打砖块')


DrawText('pyFreakOut', game_start_font, windowSurface, 
         (WINDOW_WIDTH/3), (WINDOW_HEIGHT/3 + 50))
DrawText('Press any key to start.', game_start_font, windowSurface, 
         (WINDOW_WIDTH/3)-60, (WINDOW_HEIGHT)/3+100)
pygame.display.update()
WaitForPlayerToPressKey()


# 播放背景音乐
pygame.mixer.music.play(-1, 0.0)

# 游戏主循环
while True:
    # 事件监听
    for event in pygame.event.get():
        if event.type == QUIT:
            Terminate()
        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                paddle_move_left = True
            if event.key == K_RIGHT:
                paddle_move_right = True
            if event.key == K_ESCAPE:
                Terminate()
        if event.type == KEYUP:
            if event.key == K_LEFT:
                paddle_move_left = False
            if event.key == K_RIGHT:
                paddle_move_right = False
        
    # 游戏控制流程           
    if game_state == GAME_STATE_INIT:
        # 初始化游戏
        ball_x  = random.randint(8, WINDOW_WIDTH-8)
        ball_y  = BALL_START_Y
        ball_dx = random.randint(-3, 4)
        ball_dy = random.randint( 5, 8)
        
        paddle['rect'].left = PADDLE_START_X
        paddle['rect'].top  = PADDLE_START_Y
        
        paddle_move_left  = False
        paddle_move_right = False
        
        life_left   = TOTAL_LIFE
        game_over   = False
        blocks_hit  = 0
        score       = 0
        level       = 1
        game_state  = GAME_STATE_START_LEVEL
    elif game_state == GAME_STATE_START_LEVEL:
        # 新的一关
        blocks = InitBlocks()
        game_state = GAME_STATE_RUN
    elif game_state == GAME_STATE_RUN:
        # 游戏运行
        
        # 球的运动
        ball_x += ball_dx;
        ball_y += ball_dy;
        
        if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
            ball_dx = -ball_dx
            ball_x  += ball_dx;
        elif ball_y < BALL_SIZE:
            ball_dy = -ball_dy
            ball_y  += ball_dy
        elif ball_y > WINDOW_HEIGHT-BALL_SIZE:
            if life_left == 0:
                game_state = GAME_STATE_GAMEOVER
            else:
                life_left -= 1
                # 初始化游戏
                ball_x  = paddle['rect'].left + PADDLE_WIDTH // 2
                ball_y  = BALL_START_Y
                ball_dx = random.randint(-4, 5)
                ball_dy = random.randint( 6, 9)
            
        # 检测球是否与挡板碰撞
        if ball_y > WINDOW_HEIGHT // 2:
            if (ball_x+BALL_SIZE >= paddle['rect'].left and \
                ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
                ball_y+BALL_SIZE >= paddle['rect'].top and \
                ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
                ball_dy = - ball_dy
                ball_y += ball_dy
                game_hit_sound.play()
                if paddle_move_left:
                    ball_dx -= random.randint(0, 3)
                elif paddle_move_right:
                    ball_dx += random.randint(0, 3)
                else:
                    ball_dx += random.randint(-1, 2)
                    
        # 检测球是否与砖块碰撞
        cur_x = BLOCK_ORIGIN_X
        cur_y = BLOCK_ORIGIN_Y
        for row in range(NUM_BLOCK_ROWS):
            cur_x = BLOCK_ORIGIN_X
            for col in range(NUM_BLOCK_COLUMNS):
                if blocks[row][col] != 0:
                    if (ball_x+BALL_SIZE >= cur_x and \
                        ball_x-BALL_SIZE <= cur_x+BLOCK_WIDTH and \
                        ball_y+BALL_SIZE >= cur_y and \
                        ball_y-BALL_SIZE <= cur_y+BLOCK_HEIGHT):
                        blocks[row][col] = 0
                        blocks_hit += 1
                        ball_dy = -ball_dy
                        ball_dx += random.randint(-1, 2)
                        score += 5 * (level + abs(ball_dx))
                        game_hit_sound.play()
                cur_x += BLOCK_X_GAP
            cur_y += BLOCK_Y_GAP
            
        if blocks_hit == NUM_BLOCK_ROWS * NUM_BLOCK_COLUMNS:
            level       += 1
            blocks_hit  = 0
            score       += 1000
            game_state  = GAME_STATE_START_LEVEL
            
        # 挡板的运动
        if paddle_move_left:
            paddle['rect'].left -= 8
            if paddle['rect'].left < 0:
                paddle['rect'].left = 0
        if paddle_move_right:
            paddle['rect'].left += 8
            if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
                paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
        
        # 绘制过程
        windowSurface.fill(BACKGROUND_COLOR)
        # 绘制挡板
        pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
        # 绘制小球
        pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), 
                           BALL_SIZE, 0)
        # 绘制砖块
        cur_x = BLOCK_ORIGIN_X
        cur_y = BLOCK_ORIGIN_Y
        for row in range(NUM_BLOCK_ROWS):
            cur_x = BLOCK_ORIGIN_X
            for col in range(NUM_BLOCK_COLUMNS):
                if blocks[row][col] != 0:
                    pygame.draw.rect(windowSurface, BLOCK_COLOR, 
                                     (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
                cur_x += BLOCK_X_GAP
            cur_y += BLOCK_Y_GAP
            
        # 绘制文字描述信息
        message = 'Level: ' + str(level) + '    Life: ' + str(life_left) + '    Score: ' + str(score)
        DrawText(message, text_font, windowSurface, 8, (WINDOW_HEIGHT - 16))
    elif game_state == GAME_STATE_GAMEOVER:
        DrawText('GAME OVER', game_over_font, windowSurface, 
                 (WINDOW_WIDTH / 3), (WINDOW_HEIGHT / 3))
        DrawText('Level: ' + str(level), game_over_font, windowSurface, 
                 (WINDOW_WIDTH / 3)+20, (WINDOW_HEIGHT / 3) + 50)
        DrawText('Score: ' + str(score), game_over_font, windowSurface, 
                 (WINDOW_WIDTH / 3)+20, (WINDOW_HEIGHT / 3) + 100)
        DrawText('Press any key to play again.', game_over_font, windowSurface, 
                 (WINDOW_WIDTH / 3)-80, (WINDOW_HEIGHT / 3) + 150)
        pygame.display.update()
        
        pygame.mixer.music.stop()
        game_over_sound.play()
        
        WaitForPlayerToPressKey()
        game_state = GAME_STATE_INIT
    elif game_state == GAME_STATE_SHUTDOWN:
        game_state = GAME_STATE_EXIT
    
    pygame.display.update()
    mainClock.tick(FPS + level*2)
    


哈哈,费了一晚上时间,终于有个打砖块的样子了,这是我对自己最满意的一个Python 游戏,以后加油,一定能逐渐进步~

2012-12-1      01:28
  • 20
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
制作打砖块游戏的项目说明如下: 1. 游戏介绍:打砖块游戏是一款经典的街机游戏,玩家需要用挡板控制球撞击砖块,摧毁所有砖块即可过关。 2. 游戏规则:游戏中有多种类型的砖块,不同类型的砖块有不同的耐久度和分值。玩家每次撞击砖块会得到相应的分值,当所有砖块被摧毁后,玩家即可过关。如果球从挡板下落,则玩家失败。 3. 游戏设计:游戏需要实现以下功能模块: - 球和挡板的运动控制 - 碰撞检测和反弹处理 - 砖块的生成和摧毁 - 计分和关卡控制 4. 编程实现:可以使用Python语言和Pygame库来实现打砖块游戏。具体实现方法如下: - 使用Pygame库创建游戏窗口和游戏场景 - 设计球和挡板的运动控制函数,包括键盘事件处理和运动速度控制 - 设计碰撞检测和反弹处理函数,包括球和挡板之间的碰撞、球和砖块之间的碰撞以及球和边界之间的碰撞 - 设计砖块的生成和摧毁函数,包括砖块类型的生成、砖块耐久度的控制以及砖块被摧毁后的处理 - 设计计分和关卡控制函数,包括计分的方式、过关条件的控制以及关卡的切换 5. 调试和优化:在完成代码编写后,需要进行调试和优化,确保游戏的运行稳定和流畅。可以使用Python的调试工具来进行调试,同时也可以根据游戏运行情况进行代码优化,提高游戏的性能和体验。 6. 发布和分享:完成游戏制作后,可以将游戏发布到网站或应用商店,与其他玩家分享游戏乐趣。同时,也可以将游戏源代码上传到开源社区,供其他开发者学习和参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值