打砖块

 

打砖块

 

文章连接🔗

 

Python+pyGame 打砖块游戏

 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/guzhou_diaoke/article/details/8244803

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

 

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

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

昨晚照着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几行代码,先做出一个游戏界面框架来:

 

  1.  
    '''
  2.  
    功能:使用pyGame实现一个简单的打砖块游戏
  3.  
    Created on Nov 30, 2012
  4.  
    @author: liury_lab
  5.  
    '''
  6.  
     
  7.  
    import pygame, sys, time #@UnusedImport
  8.  
    from pygame.locals import * #@UnusedWildImport
  9.  
     
  10.  
    # 一些关于宽度和高度的常量定义
  11.  
    WINDOWWIDTH = 640
  12.  
    WINDOWHEIGHT = 480
  13.  
     
  14.  
    # 一些颜色常量定义
  15.  
    BACKGROUNDCOLOR = (0, 0, 0)
  16.  
     
  17.  
    # 游戏的初始化
  18.  
    pygame.init()
  19.  
    mainClock = pygame.time.Clock()
  20.  
     
  21.  
    windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
  22.  
    pygame.display.set_caption('打砖块')
  23.  
     
  24.  
    # 游戏主循环
  25.  
    while True:
  26.  
    # 事件监听
  27.  
    for event in pygame.event.get():
  28.  
    if event.type == QUIT:
  29.  
    pygame.quit()
  30.  
    exit()
  31.  
     
  32.  
    windowSurface.fill(BACKGROUNDCOLOR)
  33.  
     
  34.  
    pygame.display.update()
  35.  
    mainClock.tick(30)
  36.  
     

 


下面画个会动的小球吧:

 

  1.  
    # 游戏主循环
  2.  
    while True:
  3.  
    # 事件监听
  4.  
    for event in pygame.event.get():
  5.  
    if event.type == QUIT:
  6.  
    pygame.quit()
  7.  
    exit()
  8.  
     
  9.  
    if game_state == GAME_STATE_INIT:
  10.  
    # 初始化游戏
  11.  
    ball_x = random.randint(8, WINDOW_WIDTH-8)
  12.  
    ball_y = BALL_START_Y
  13.  
    ball_dx = random.randint(-4, 4)
  14.  
    ball_dy = random.randint( 6, 8)
  15.  
     
  16.  
    game_state = GAME_STATE_START_LEVEL
  17.  
    elif game_state == GAME_STATE_START_LEVEL:
  18.  
    # 新的一关
  19.  
    game_state = GAME_STATE_RUN
  20.  
    elif game_state == GAME_STATE_RUN:
  21.  
    # 游戏运行
  22.  
    ball_x += ball_dx;
  23.  
    ball_y += ball_dy;
  24.  
    windowSurface.fill(BACKGROUND_COLOR)
  25.  
    pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), BALL_SIZE, 0)
  26.  
    elif game_state == GAME_STATE_SHUTDOWN:
  27.  
    game_state = GAME_STATE_EXIT
  28.  
     
  29.  
    pygame.display.update()
  30.  
    mainClock.tick(30)


 

 

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

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

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

3. 碰撞检测

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

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

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

 

  1.  
    elif game_state == GAME_STATE_RUN:
  2.  
    # 游戏运行
  3.  
    ball_x += ball_dx;
  4.  
    ball_y += ball_dy;
  5.  
     
  6.  
    if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  7.  
    ball_dx = -ball_dx
  8.  
    ball_x += ball_dx;
  9.  
    elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
  10.  
    ball_dy = -ball_dy
  11.  
    ball_y += ball_dy

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

 

4. 挡板绘制和移动

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

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

 

  1.  
    # 游戏主循环
  2.  
    while True:
  3.  
    # 事件监听
  4.  
    for event in pygame.event.get():
  5.  
    if event.type == QUIT:
  6.  
    pygame.quit()
  7.  
    exit()
  8.  
    if event.type == KEYDOWN:
  9.  
    if event.key == K_LEFT:
  10.  
    paddle_move_left = True
  11.  
    if event.key == K_RIGHT:
  12.  
    paddle_move_right = True
  13.  
    if event.type == KEYUP:
  14.  
    if event.key == K_LEFT:
  15.  
    paddle_move_left = False
  16.  
    if event.key == K_RIGHT:
  17.  
    paddle_move_right = False
  18.  
    # 游戏控制流程
  19.  
    if game_state == GAME_STATE_INIT:
  20.  
    # 初始化游戏
  21.  
    ball_x = random.randint(8, WINDOW_WIDTH-8)
  22.  
    ball_y = BALL_START_Y
  23.  
    ball_dx = random.randint(-4, 4)
  24.  
    ball_dy = random.randint( 6, 8)
  25.  
     
  26.  
    paddle['rect'].left = PADDLE_START_X
  27.  
    paddle['rect'].top = PADDLE_START_Y
  28.  
     
  29.  
    paddle_move_left = False
  30.  
    paddle_move_right = False
  31.  
     
  32.  
    game_state = GAME_STATE_START_LEVEL
  33.  
    elif game_state == GAME_STATE_START_LEVEL:
  34.  
    # 新的一关
  35.  
    game_state = GAME_STATE_RUN
  36.  
    elif game_state == GAME_STATE_RUN:
  37.  
    # 游戏运行
  38.  
     
  39.  
    # 球的运动
  40.  
    ball_x += ball_dx;
  41.  
    ball_y += ball_dy;
  42.  
     
  43.  
    if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  44.  
    ball_dx = -ball_dx
  45.  
    ball_x += ball_dx;
  46.  
    elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
  47.  
    ball_dy = -ball_dy
  48.  
    ball_y += ball_dy
  49.  
     
  50.  
    # 挡板的运动
  51.  
    if paddle_move_left:
  52.  
    paddle['rect'].left -= 8
  53.  
    if paddle['rect'].left < 0:
  54.  
    paddle['rect'].left = 0
  55.  
    if paddle_move_right:
  56.  
    paddle['rect'].left += 8
  57.  
    if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
  58.  
    paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
  59.  
     
  60.  
    # 绘制过程
  61.  
    windowSurface.fill(BACKGROUND_COLOR)
  62.  
    pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
  63.  
    pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), BALL_SIZE, 0)
  64.  
    elif game_state == GAME_STATE_SHUTDOWN:
  65.  
    game_state = GAME_STATE_EXIT
  66.  
     
  67.  
    pygame.display.update()
  68.  
    mainClock.tick(30)

 

5. 砖块的绘制

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

初始化砖块二维数组:

 

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

砖块的绘制:

 

 

  1.  
    elif game_state == GAME_STATE_START_LEVEL:
  2.  
    # 新的一关
  3.  
    blocks = InitBlocks()
  4.  
    game_state = GAME_STATE_RUN
  5.  
    elif game_state == GAME_STATE_RUN:
  6.  
    # 游戏运行
  7.  
     
  8.  
    # 球的运动
  9.  
    ball_x += ball_dx;
  10.  
    ball_y += ball_dy;
  11.  
     
  12.  
    if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  13.  
    ball_dx = -ball_dx
  14.  
    ball_x += ball_dx;
  15.  
    elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
  16.  
    ball_dy = -ball_dy
  17.  
    ball_y += ball_dy
  18.  
     
  19.  
    # 挡板的运动
  20.  
    if paddle_move_left:
  21.  
    paddle['rect'].left -= 8
  22.  
    if paddle['rect'].left < 0:
  23.  
    paddle['rect'].left = 0
  24.  
    if paddle_move_right:
  25.  
    paddle['rect'].left += 8
  26.  
    if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
  27.  
    paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
  28.  
     
  29.  
    # 绘制过程
  30.  
    windowSurface.fill(BACKGROUND_COLOR)
  31.  
    # 绘制挡板
  32.  
    pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
  33.  
    # 绘制小球
  34.  
    pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y),
  35.  
    BALL_SIZE, 0)
  36.  
    # 绘制砖块
  37.  
    cur_x = BLOCK_ORIGIN_X
  38.  
    cur_y = BLOCK_ORIGIN_Y
  39.  
    for row in range(NUM_BLOCK_ROWS):
  40.  
    cur_x = BLOCK_ORIGIN_X
  41.  
    for col in range(NUM_BLOCK_COLUMNS):
  42.  
    print(blocks[row][col])
  43.  
    if (blocks[row][col] == 1):
  44.  
    pygame.draw.rect(windowSurface, BLOCK_COLOR,
  45.  
    (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
  46.  
    cur_x += BLOCK_X_GAP
  47.  
    cur_y += BLOCK_Y_GAP


 

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

6. 游戏流程和控制逻辑

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

1)把砖块打破

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

3)生命用完了则Game Over

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

    

  1.  
    elif game_state == GAME_STATE_RUN:
  2.  
    # 游戏运行
  3.  
     
  4.  
    # 球的运动
  5.  
    ball_x += ball_dx;
  6.  
    ball_y += ball_dy;
  7.  
     
  8.  
    if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  9.  
    ball_dx = -ball_dx
  10.  
    ball_x += ball_dx;
  11.  
    elif ball_y < BALL_SIZE:
  12.  
    ball_dy = -ball_dy
  13.  
    ball_y += ball_dy
  14.  
    elif ball_y > WINDOW_HEIGHT-BALL_SIZE:
  15.  
    if life_left == 0:
  16.  
    game_state = GAME_STATE_GAMEOVER
  17.  
    else:
  18.  
    life_left -= 1
  19.  
    # 初始化游戏
  20.  
    ball_x = paddle['rect'].left + PADDLE_WIDTH // 2
  21.  
    ball_y = BALL_START_Y
  22.  
    ball_dx = random.randint(-4, 5)
  23.  
    ball_dy = random.randint( 6, 9)
  24.  
     
  25.  
    # 检测球是否与挡板碰撞
  26.  
    if ball_y > WINDOW_HEIGHT // 2:
  27.  
    if (ball_x+BALL_SIZE >= paddle['rect'].left and \
  28.  
    ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
  29.  
    ball_y+BALL_SIZE >= paddle['rect'].top and \
  30.  
    ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
  31.  
    ball_dy = - ball_dy
  32.  
    ball_y += ball_dy
  33.  
    if paddle_move_left:
  34.  
    ball_dx -= random.randint(0, 2)
  35.  
    elif paddle_move_right:
  36.  
    ball_dx += random.randint(0, 2)
  37.  
    else:
  38.  
    ball_dx += random.randint(-1, 2)
  39.  
     
  40.  
    # 检测球是否与砖块碰撞
  41.  
    cur_x = BLOCK_ORIGIN_X
  42.  
    cur_y = BLOCK_ORIGIN_Y
  43.  
    for row in range(NUM_BLOCK_ROWS):
  44.  
    cur_x = BLOCK_ORIGIN_X
  45.  
    for col in range(NUM_BLOCK_COLUMNS):
  46.  
    if blocks[row][col] != 0:
  47.  
    if (ball_x+BALL_SIZE >= cur_x and \
  48.  
    ball_x-BALL_SIZE <= cur_x+BLOCK_WIDTH and \
  49.  
    ball_y+BALL_SIZE >= cur_y and \
  50.  
    ball_y-BALL_SIZE <= cur_y+BLOCK_HEIGHT):
  51.  
    blocks[row][col] = 0
  52.  
    blocks_hit += 1
  53.  
    ball_dy = -ball_dy
  54.  
    ball_dx += random.randint(-1, 2)
  55.  
    score += 5 * (level + abs(ball_dx))
  56.  
    cur_x += BLOCK_X_GAP
  57.  
    cur_y += BLOCK_Y_GAP
  58.  
     
  59.  
    if blocks_hit == NUM_BLOCK_ROWS * NUM_BLOCK_COLUMNS:
  60.  
    level += 1
  61.  
    game_state = GAME_STATE_START_LEVEL
  62.  
     
  63.  
    # 挡板的运动
  64.  
    if paddle_move_left:
  65.  
    paddle['rect'].left -= 8
  66.  
    if paddle['rect'].left < 0:
  67.  
    paddle['rect'].left = 0
  68.  
    if paddle_move_right:
  69.  
    paddle['rect'].left += 8
  70.  
    if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
  71.  
    paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
  72.  
     
  73.  
    # 绘制过程
  74.  
    windowSurface.fill(BACKGROUND_COLOR)
  75.  
    # 绘制挡板
  76.  
    pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
  77.  
    # 绘制小球
  78.  
    pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y),
  79.  
    BALL_SIZE, 0)
  80.  
    # 绘制砖块
  81.  
    cur_x = BLOCK_ORIGIN_X
  82.  
    cur_y = BLOCK_ORIGIN_Y
  83.  
    for row in range(NUM_BLOCK_ROWS):
  84.  
    cur_x = BLOCK_ORIGIN_X
  85.  
    for col in range(NUM_BLOCK_COLUMNS):
  86.  
    if blocks[row][col] != 0:
  87.  
    pygame.draw.rect(windowSurface, BLOCK_COLOR,
  88.  
    (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
  89.  
    cur_x += BLOCK_X_GAP
  90.  
    cur_y += BLOCK_Y_GAP
  91.  
    elif game_state == GAME_STATE_GAMEOVER:
  92.  
    continue
  93.  
    elif game_state == GAME_STATE_SHUTDOWN:
  94.  
    game_state = GAME_STATE_EXIT
  95.  
     
  96.  
    pygame.display.update()
  97.  
    mainClock.tick(30)


 

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

绘制函数:
  1.  
    # 显示文字
  2.  
    def DrawText(text, font, surface, x, y):
  3.  
    text_obj = font.render(text, 1, TEXT_COLOR)
  4.  
    text_rect = text_obj.get_rect()
  5.  
    text_rect.topleft = (x, y)
  6.  
    surface.blit(text_obj, text_rect)
 
合理计算分数,并设置过关:
比如每过一关加1000分,打完所有砖块则进入下一关。
左下角显示游戏信息,如关卡、分数、生命等,游戏结束显示Game Over信息

 

  1.  
    # 游戏主循环
  2.  
    while True:
  3.  
    # 事件监听
  4.  
    for event in pygame.event.get():
  5.  
    if event.type == QUIT:
  6.  
    pygame.quit()
  7.  
    exit()
  8.  
    if event.type == KEYDOWN:
  9.  
    if event.key == K_LEFT:
  10.  
    paddle_move_left = True
  11.  
    if event.key == K_RIGHT:
  12.  
    paddle_move_right = True
  13.  
    if event.type == KEYUP:
  14.  
    if event.key == K_LEFT:
  15.  
    paddle_move_left = False
  16.  
    if event.key == K_RIGHT:
  17.  
    paddle_move_right = False
  18.  
    # 游戏控制流程
  19.  
    if game_state == GAME_STATE_INIT:
  20.  
    # 初始化游戏
  21.  
    ball_x = random.randint(8, WINDOW_WIDTH-8)
  22.  
    ball_y = BALL_START_Y
  23.  
    ball_dx = random.randint(-3, 4)
  24.  
    ball_dy = random.randint( 5, 8)
  25.  
     
  26.  
    paddle['rect'].left = PADDLE_START_X
  27.  
    paddle['rect'].top = PADDLE_START_Y
  28.  
     
  29.  
    paddle_move_left = False
  30.  
    paddle_move_right = False
  31.  
     
  32.  
    life_left = TOTAL_LIFE
  33.  
    game_over = False
  34.  
    blocks_hit = 0
  35.  
    score = 0
  36.  
    level = 1
  37.  
    game_state = GAME_STATE_START_LEVEL
  38.  
    elif game_state == GAME_STATE_START_LEVEL:
  39.  
    # 新的一关
  40.  
    blocks = InitBlocks()
  41.  
    game_state = GAME_STATE_RUN
  42.  
    elif game_state == GAME_STATE_RUN:
  43.  
    # 游戏运行
  44.  
     
  45.  
    # 球的运动
  46.  
    ball_x += ball_dx;
  47.  
    ball_y += ball_dy;
  48.  
     
  49.  
    if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  50.  
    ball_dx = -ball_dx
  51.  
    ball_x += ball_dx;
  52.  
    elif ball_y < BALL_SIZE:
  53.  
    ball_dy = -ball_dy
  54.  
    ball_y += ball_dy
  55.  
    elif ball_y > WINDOW_HEIGHT-BALL_SIZE:
  56.  
    if life_left == 0:
  57.  
    game_state = GAME_STATE_GAMEOVER
  58.  
    else:
  59.  
    life_left -= 1
  60.  
    # 初始化游戏
  61.  
    ball_x = paddle['rect'].left + PADDLE_WIDTH // 2
  62.  
    ball_y = BALL_START_Y
  63.  
    ball_dx = random.randint(-4, 5)
  64.  
    ball_dy = random.randint( 6, 9)
  65.  
     
  66.  
    # 检测球是否与挡板碰撞
  67.  
    if ball_y > WINDOW_HEIGHT // 2:
  68.  
    if (ball_x+BALL_SIZE >= paddle['rect'].left and \
  69.  
    ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
  70.  
    ball_y+BALL_SIZE >= paddle['rect'].top and \
  71.  
    ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
  72.  
    ball_dy = - ball_dy
  73.  
    ball_y += ball_dy
  74.  
    if paddle_move_left:
  75.  
    ball_dx -= random.randint(0, 2)
  76.  
    elif paddle_move_right:
  77.  
    ball_dx += random.randint(0, 2)
  78.  
    else:
  79.  
    ball_dx += random.randint(-1, 2)
  80.  
     
  81.  
    # 检测球是否与砖块碰撞
  82.  
    cur_x = BLOCK_ORIGIN_X
  83.  
    cur_y = BLOCK_ORIGIN_Y
  84.  
    for row in range(NUM_BLOCK_ROWS):
  85.  
    cur_x = BLOCK_ORIGIN_X
  86.  
    for col in range(NUM_BLOCK_COLUMNS):
  87.  
    if blocks[row][col] != 0:
  88.  
    if (ball_x+BALL_SIZE >= cur_x and \
  89.  
    ball_x-BALL_SIZE <= cur_x+BLOCK_WIDTH and \
  90.  
    ball_y+BALL_SIZE >= cur_y and \
  91.  
    ball_y-BALL_SIZE <= cur_y+BLOCK_HEIGHT):
  92.  
    blocks[row][col] = 0
  93.  
    blocks_hit += 1
  94.  
    ball_dy = -ball_dy
  95.  
    ball_dx += random.randint(-1, 2)
  96.  
    score += 5 * (level + abs(ball_dx))
  97.  
    cur_x += BLOCK_X_GAP
  98.  
    cur_y += BLOCK_Y_GAP
  99.  
     
  100.  
    if blocks_hit == NUM_BLOCK_ROWS * NUM_BLOCK_COLUMNS:
  101.  
    level += 1
  102.  
    blocks_hit = 0
  103.  
    score += 1000
  104.  
    game_state = GAME_STATE_START_LEVEL
  105.  
     
  106.  
    # 挡板的运动
  107.  
    if paddle_move_left:
  108.  
    paddle['rect'].left -= 8
  109.  
    if paddle['rect'].left < 0:
  110.  
    paddle['rect'].left = 0
  111.  
    if paddle_move_right:
  112.  
    paddle['rect'].left += 8
  113.  
    if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
  114.  
    paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
  115.  
     
  116.  
    # 绘制过程
  117.  
    windowSurface.fill(BACKGROUND_COLOR)
  118.  
    # 绘制挡板
  119.  
    pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
  120.  
    # 绘制小球
  121.  
    pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y),
  122.  
    BALL_SIZE, 0)
  123.  
    # 绘制砖块
  124.  
    cur_x = BLOCK_ORIGIN_X
  125.  
    cur_y = BLOCK_ORIGIN_Y
  126.  
    for row in range(NUM_BLOCK_ROWS):
  127.  
    cur_x = BLOCK_ORIGIN_X
  128.  
    for col in range(NUM_BLOCK_COLUMNS):
  129.  
    if blocks[row][col] != 0:
  130.  
    pygame.draw.rect(windowSurface, BLOCK_COLOR,
  131.  
    (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
  132.  
    cur_x += BLOCK_X_GAP
  133.  
    cur_y += BLOCK_Y_GAP
  134.  
     
  135.  
    # 绘制文字描述信息
  136.  
    message = 'Level: ' + str(level) + ' Life: ' + str(life_left) + ' Score: ' + str(score)
  137.  
    DrawText(message, text_font, windowSurface, 8, (WINDOW_HEIGHT - 16))
  138.  
    elif game_state == GAME_STATE_GAMEOVER:
  139.  
    DrawText('GAME OVER', game_over_font, windowSurface, (WINDOW_WIDTH / 3), (WINDOW_HEIGHT / 3))
  140.  
    DrawText('Score: ' + str(score), game_over_font, windowSurface,
  141.  
    (WINDOW_WIDTH / 3)+20, (WINDOW_HEIGHT / 3) + 50)
  142.  
    elif game_state == GAME_STATE_SHUTDOWN:
  143.  
    game_state = GAME_STATE_EXIT
  144.  
     
  145.  
    pygame.display.update()
  146.  
    mainClock.tick(25 + level*2)


 

 

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

 

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

开始及停止播放:

 

 

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

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

 

9. 增加个开始画面

 

 

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


 

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

 

10. 完整代码

  1.  
    '''
  2.  
    功能:使用pyGame实现一个简单的打砖块游戏
  3.  
    Created on Nov 30, 2012
  4.  
    @author: liury_lab
  5.  
    '''
  6.  
     
  7.  
    import pygame, sys, time, random #@UnusedImport
  8.  
    from pygame.locals import * #@UnusedWildImport
  9.  
     
  10.  
    # 一些关于窗口的常量定义
  11.  
    WINDOW_WIDTH = 640
  12.  
    WINDOW_HEIGHT = 480
  13.  
     
  14.  
    # 游戏状态常量定义
  15.  
    GAME_STATE_INIT = 0
  16.  
    GAME_STATE_START_LEVEL = 1
  17.  
    GAME_STATE_RUN = 2
  18.  
    GAME_STATE_GAMEOVER = 3
  19.  
    GAME_STATE_SHUTDOWN = 4
  20.  
    GAME_STATE_EXIT = 5
  21.  
     
  22.  
    # 小球的常量定义
  23.  
    BALL_START_Y = (WINDOW_HEIGHT//2)
  24.  
    BALL_SIZE = 4
  25.  
     
  26.  
    # 挡板的常量定义
  27.  
    PADDLE_START_X = (WINDOW_WIDTH/2 - 16)
  28.  
    PADDLE_START_Y = (WINDOW_HEIGHT - 32);
  29.  
    PADDLE_WIDTH = 32
  30.  
    PADDLE_HEIGHT = 8
  31.  
     
  32.  
    # 砖块的常量定义
  33.  
    NUM_BLOCK_ROWS = 6
  34.  
    NUM_BLOCK_COLUMNS = 8
  35.  
    BLOCK_WIDTH = 64
  36.  
    BLOCK_HEIGHT = 16
  37.  
    BLOCK_ORIGIN_X = 8
  38.  
    BLOCK_ORIGIN_Y = 8
  39.  
    BLOCK_X_GAP = 80
  40.  
    BLOCK_Y_GAP = 32
  41.  
     
  42.  
    # 一些颜色常量定义
  43.  
    BACKGROUND_COLOR = (0, 0, 0)
  44.  
    BALL_COLOR = (0, 0, 255)
  45.  
    PADDLE_COLOR = (128, 64, 64)
  46.  
    BLOCK_COLOR = (255, 128, 0)
  47.  
    TEXT_COLOR = (255, 255, 255)
  48.  
     
  49.  
    # 游戏的一些属性信息
  50.  
    TOTAL_LIFE = 5
  51.  
    FPS = 25
  52.  
     
  53.  
    # 初始化砖块数组
  54.  
    def InitBlocks():
  55.  
    #blocks = [[1] * NUM_BLOCK_COLUMNS] * NUM_BLOCK_ROWS
  56.  
    blocks = []
  57.  
    for i in range(NUM_BLOCK_ROWS): #@UnusedVarialbe
  58.  
    blocks.append([i+1] * NUM_BLOCK_COLUMNS)
  59.  
    return blocks
  60.  
     
  61.  
    # 检测小球是否与挡板或者砖块碰撞
  62.  
    def ProcessBall(blocks, ball_x, ball_y, paddle):
  63.  
    if (ball_y > WINDOW_HEIGHT//2):
  64.  
    if (ball_x+BALL_SIZE >= paddle['rect'].left and \
  65.  
    ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
  66.  
    ball_y+BALL_SIZE >= paddle['rect'].top and \
  67.  
    ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
  68.  
    return None
  69.  
     
  70.  
    # 显示文字
  71.  
    def DrawText(text, font, surface, x, y):
  72.  
    text_obj = font.render(text, 1, TEXT_COLOR)
  73.  
    text_rect = text_obj.get_rect()
  74.  
    text_rect.topleft = (x, y)
  75.  
    surface.blit(text_obj, text_rect)
  76.  
     
  77.  
    # 退出游戏
  78.  
    def Terminate():
  79.  
    pygame.quit()
  80.  
    sys.exit()
  81.  
     
  82.  
    # 等待用户输入
  83.  
    def WaitForPlayerToPressKey():
  84.  
    while True:
  85.  
    for event in pygame.event.get():
  86.  
    if event.type == QUIT:
  87.  
    Terminate()
  88.  
    if event.type == KEYDOWN:
  89.  
    if event.key == K_ESCAPE:
  90.  
    Terminate()
  91.  
    return
  92.  
     
  93.  
    # 游戏界面的初始化
  94.  
    pygame.init()
  95.  
    mainClock = pygame.time.Clock()
  96.  
     
  97.  
    # 小球的位置和速度
  98.  
    ball_x = 0
  99.  
    ball_y = 0
  100.  
    ball_dx = 0
  101.  
    ball_dy = 0
  102.  
     
  103.  
    # 挡板的运动控制
  104.  
    paddle_move_left = False
  105.  
    paddle_move_right = False
  106.  
     
  107.  
    # 挡板的位置和颜色
  108.  
    paddle = {'rect' :pygame.Rect(0, 0, PADDLE_WIDTH, PADDLE_HEIGHT),
  109.  
    'color': PADDLE_COLOR}
  110.  
     
  111.  
    # 游戏状态
  112.  
    game_state = GAME_STATE_INIT
  113.  
    blocks = []
  114.  
    life_left = TOTAL_LIFE
  115.  
    game_over = False
  116.  
    blocks_hit = 0
  117.  
    score = 0
  118.  
    level = 1
  119.  
     
  120.  
    game_start_font = pygame.font.SysFont(None, 48)
  121.  
    game_over_font = pygame.font.SysFont(None, 48)
  122.  
    text_font = pygame.font.SysFont(None, 20)
  123.  
     
  124.  
    game_over_sound = pygame.mixer.Sound('gameover.wav')
  125.  
    game_hit_sound = pygame.mixer.Sound('hit.wav')
  126.  
    pygame.mixer.music.load('background.mp3')
  127.  
     
  128.  
    windowSurface = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), 0, 32)
  129.  
    pygame.display.set_caption('打砖块')
  130.  
     
  131.  
     
  132.  
    DrawText('pyFreakOut', game_start_font, windowSurface,
  133.  
    (WINDOW_WIDTH/3), (WINDOW_HEIGHT/3 + 50))
  134.  
    DrawText('Press any key to start.', game_start_font, windowSurface,
  135.  
    (WINDOW_WIDTH/3)-60, (WINDOW_HEIGHT)/3+100)
  136.  
    pygame.display.update()
  137.  
    WaitForPlayerToPressKey()
  138.  
     
  139.  
     
  140.  
    # 播放背景音乐
  141.  
    pygame.mixer.music.play(-1, 0.0)
  142.  
     
  143.  
    # 游戏主循环
  144.  
    while True:
  145.  
    # 事件监听
  146.  
    for event in pygame.event.get():
  147.  
    if event.type == QUIT:
  148.  
    Terminate()
  149.  
    if event.type == KEYDOWN:
  150.  
    if event.key == K_LEFT:
  151.  
    paddle_move_left = True
  152.  
    if event.key == K_RIGHT:
  153.  
    paddle_move_right = True
  154.  
    if event.key == K_ESCAPE:
  155.  
    Terminate()
  156.  
    if event.type == KEYUP:
  157.  
    if event.key == K_LEFT:
  158.  
    paddle_move_left = False
  159.  
    if event.key == K_RIGHT:
  160.  
    paddle_move_right = False
  161.  
     
  162.  
    # 游戏控制流程
  163.  
    if game_state == GAME_STATE_INIT:
  164.  
    # 初始化游戏
  165.  
    ball_x = random.randint(8, WINDOW_WIDTH-8)
  166.  
    ball_y = BALL_START_Y
  167.  
    ball_dx = random.randint(-3, 4)
  168.  
    ball_dy = random.randint( 5, 8)
  169.  
     
  170.  
    paddle['rect'].left = PADDLE_START_X
  171.  
    paddle['rect'].top = PADDLE_START_Y
  172.  
     
  173.  
    paddle_move_left = False
  174.  
    paddle_move_right = False
  175.  
     
  176.  
    life_left = TOTAL_LIFE
  177.  
    game_over = False
  178.  
    blocks_hit = 0
  179.  
    score = 0
  180.  
    level = 1
  181.  
    game_state = GAME_STATE_START_LEVEL
  182.  
    elif game_state == GAME_STATE_START_LEVEL:
  183.  
    # 新的一关
  184.  
    blocks = InitBlocks()
  185.  
    game_state = GAME_STATE_RUN
  186.  
    elif game_state == GAME_STATE_RUN:
  187.  
    # 游戏运行
  188.  
     
  189.  
    # 球的运动
  190.  
    ball_x += ball_dx;
  191.  
    ball_y += ball_dy;
  192.  
     
  193.  
    if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  194.  
    ball_dx = -ball_dx
  195.  
    ball_x += ball_dx;
  196.  
    elif ball_y < BALL_SIZE:
  197.  
    ball_dy = -ball_dy
  198.  
    ball_y += ball_dy
  199.  
    elif ball_y > WINDOW_HEIGHT-BALL_SIZE:
  200.  
    if life_left == 0:
  201.  
    game_state = GAME_STATE_GAMEOVER
  202.  
    else:
  203.  
    life_left -= 1
  204.  
    # 初始化游戏
  205.  
    ball_x = paddle['rect'].left + PADDLE_WIDTH // 2
  206.  
    ball_y = BALL_START_Y
  207.  
    ball_dx = random.randint(-4, 5)
  208.  
    ball_dy = random.randint( 6, 9)
  209.  
     
  210.  
    # 检测球是否与挡板碰撞
  211.  
    if ball_y > WINDOW_HEIGHT // 2:
  212.  
    if (ball_x+BALL_SIZE >= paddle['rect'].left and \
  213.  
    ball_x-BALL_SIZE <= paddle['rect'].left+PADDLE_WIDTH and \
  214.  
    ball_y+BALL_SIZE >= paddle['rect'].top and \
  215.  
    ball_y-BALL_SIZE <= paddle['rect'].top+PADDLE_HEIGHT):
  216.  
    ball_dy = - ball_dy
  217.  
    ball_y += ball_dy
  218.  
    game_hit_sound.play()
  219.  
    if paddle_move_left:
  220.  
    ball_dx -= random.randint(0, 3)
  221.  
    elif paddle_move_right:
  222.  
    ball_dx += random.randint(0, 3)
  223.  
    else:
  224.  
    ball_dx += random.randint(-1, 2)
  225.  
     
  226.  
    # 检测球是否与砖块碰撞
  227.  
    cur_x = BLOCK_ORIGIN_X
  228.  
    cur_y = BLOCK_ORIGIN_Y
  229.  
    for row in range(NUM_BLOCK_ROWS):
  230.  
    cur_x = BLOCK_ORIGIN_X
  231.  
    for col in range(NUM_BLOCK_COLUMNS):
  232.  
    if blocks[row][col] != 0:
  233.  
    if (ball_x+BALL_SIZE >= cur_x and \
  234.  
    ball_x-BALL_SIZE <= cur_x+BLOCK_WIDTH and \
  235.  
    ball_y+BALL_SIZE >= cur_y and \
  236.  
    ball_y-BALL_SIZE <= cur_y+BLOCK_HEIGHT):
  237.  
    blocks[row][col] = 0
  238.  
    blocks_hit += 1
  239.  
    ball_dy = -ball_dy
  240.  
    ball_dx += random.randint(-1, 2)
  241.  
    score += 5 * (level + abs(ball_dx))
  242.  
    game_hit_sound.play()
  243.  
    cur_x += BLOCK_X_GAP
  244.  
    cur_y += BLOCK_Y_GAP
  245.  
     
  246.  
    if blocks_hit == NUM_BLOCK_ROWS * NUM_BLOCK_COLUMNS:
  247.  
    level += 1
  248.  
    blocks_hit = 0
  249.  
    score += 1000
  250.  
    game_state = GAME_STATE_START_LEVEL
  251.  
     
  252.  
    # 挡板的运动
  253.  
    if paddle_move_left:
  254.  
    paddle['rect'].left -= 8
  255.  
    if paddle['rect'].left < 0:
  256.  
    paddle['rect'].left = 0
  257.  
    if paddle_move_right:
  258.  
    paddle['rect'].left += 8
  259.  
    if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
  260.  
    paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
  261.  
     
  262.  
    # 绘制过程
  263.  
    windowSurface.fill(BACKGROUND_COLOR)
  264.  
    # 绘制挡板
  265.  
    pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
  266.  
    # 绘制小球
  267.  
    pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y),
  268.  
    BALL_SIZE, 0)
  269.  
    # 绘制砖块
  270.  
    cur_x = BLOCK_ORIGIN_X
  271.  
    cur_y = BLOCK_ORIGIN_Y
  272.  
    for row in range(NUM_BLOCK_ROWS):
  273.  
    cur_x = BLOCK_ORIGIN_X
  274.  
    for col in range(NUM_BLOCK_COLUMNS):
  275.  
    if blocks[row][col] != 0:
  276.  
    pygame.draw.rect(windowSurface, BLOCK_COLOR,
  277.  
    (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
  278.  
    cur_x += BLOCK_X_GAP
  279.  
    cur_y += BLOCK_Y_GAP
  280.  
     
  281.  
    # 绘制文字描述信息
  282.  
    message = 'Level: ' + str(level) + ' Life: ' + str(life_left) + ' Score: ' + str(score)
  283.  
    DrawText(message, text_font, windowSurface, 8, (WINDOW_HEIGHT - 16))
  284.  
    elif game_state == GAME_STATE_GAMEOVER:
  285.  
    DrawText('GAME OVER', game_over_font, windowSurface,
  286.  
    (WINDOW_WIDTH / 3), (WINDOW_HEIGHT / 3))
  287.  
    DrawText('Level: ' + str(level), game_over_font, windowSurface,
  288.  
    (WINDOW_WIDTH / 3)+20, (WINDOW_HEIGHT / 3) + 50)
  289.  
    DrawText('Score: ' + str(score), game_over_font, windowSurface,
  290.  
    (WINDOW_WIDTH / 3)+20, (WINDOW_HEIGHT / 3) + 100)
  291.  
    DrawText('Press any key to play again.', game_over_font, windowSurface,
  292.  
    (WINDOW_WIDTH / 3)-80, (WINDOW_HEIGHT / 3) + 150)
  293.  
    pygame.display.update()
  294.  
     
  295.  
    pygame.mixer.music.stop()
  296.  
    game_over_sound.play()
  297.  
     
  298.  
    WaitForPlayerToPressKey()
  299.  
    game_state = GAME_STATE_INIT
  300.  
    elif game_state == GAME_STATE_SHUTDOWN:
  301.  
    game_state = GAME_STATE_EXIT
  302.  
     
  303.  
    pygame.display.update()
  304.  
    mainClock.tick(FPS + level*2)
  305.  
     


哈哈,费了一晚上时间,终于有个打砖块的样子了,这是我对自己最满意的一个Python 游戏,以后加油,一定能逐渐进步~
 
2012-12-1      01:28
posted @ 2019-01-08 16:02  王庆帅  阅读(164)  评论(0)    收藏  举报