当前位置:   article > 正文

Python+pyGame 打砖块游戏_python打砖块游戏增加分数

python打砖块游戏增加分数

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


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

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

昨晚照着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. import pygame, sys, time #@UnusedImport
  7. from pygame.locals import * #@UnusedWildImport
  8. # 一些关于宽度和高度的常量定义
  9. WINDOWWIDTH = 640
  10. WINDOWHEIGHT = 480
  11. # 一些颜色常量定义
  12. BACKGROUNDCOLOR = (0, 0, 0)
  13. # 游戏的初始化
  14. pygame.init()
  15. mainClock = pygame.time.Clock()
  16. windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
  17. pygame.display.set_caption('打砖块')
  18. # 游戏主循环
  19. while True:
  20. # 事件监听
  21. for event in pygame.event.get():
  22. if event.type == QUIT:
  23. pygame.quit()
  24. exit()
  25. windowSurface.fill(BACKGROUNDCOLOR)
  26. pygame.display.update()
  27. mainClock.tick(30)


下面画个会动的小球吧:

  1. # 游戏主循环
  2. while True:
  3. # 事件监听
  4. for event in pygame.event.get():
  5. if event.type == QUIT:
  6. pygame.quit()
  7. exit()
  8. if game_state == GAME_STATE_INIT:
  9. # 初始化游戏
  10. ball_x = random.randint(8, WINDOW_WIDTH-8)
  11. ball_y = BALL_START_Y
  12. ball_dx = random.randint(-4, 4)
  13. ball_dy = random.randint( 6, 8)
  14. game_state = GAME_STATE_START_LEVEL
  15. elif game_state == GAME_STATE_START_LEVEL:
  16. # 新的一关
  17. game_state = GAME_STATE_RUN
  18. elif game_state == GAME_STATE_RUN:
  19. # 游戏运行
  20. ball_x += ball_dx;
  21. ball_y += ball_dy;
  22. windowSurface.fill(BACKGROUND_COLOR)
  23. pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), BALL_SIZE, 0)
  24. elif game_state == GAME_STATE_SHUTDOWN:
  25. game_state = GAME_STATE_EXIT
  26. pygame.display.update()
  27. 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. if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  6. ball_dx = -ball_dx
  7. ball_x += ball_dx;
  8. elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
  9. ball_dy = -ball_dy
  10. 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. paddle['rect'].left = PADDLE_START_X
  26. paddle['rect'].top = PADDLE_START_Y
  27. paddle_move_left = False
  28. paddle_move_right = False
  29. game_state = GAME_STATE_START_LEVEL
  30. elif game_state == GAME_STATE_START_LEVEL:
  31. # 新的一关
  32. game_state = GAME_STATE_RUN
  33. elif game_state == GAME_STATE_RUN:
  34. # 游戏运行
  35. # 球的运动
  36. ball_x += ball_dx;
  37. ball_y += ball_dy;
  38. if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  39. ball_dx = -ball_dx
  40. ball_x += ball_dx;
  41. elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
  42. ball_dy = -ball_dy
  43. ball_y += ball_dy
  44. # 挡板的运动
  45. if paddle_move_left:
  46. paddle['rect'].left -= 8
  47. if paddle['rect'].left < 0:
  48. paddle['rect'].left = 0
  49. if paddle_move_right:
  50. paddle['rect'].left += 8
  51. if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
  52. paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
  53. # 绘制过程
  54. windowSurface.fill(BACKGROUND_COLOR)
  55. pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
  56. pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y), BALL_SIZE, 0)
  57. elif game_state == GAME_STATE_SHUTDOWN:
  58. game_state = GAME_STATE_EXIT
  59. pygame.display.update()
  60. 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. ball_x += ball_dx;
  9. ball_y += ball_dy;
  10. if ball_x > (WINDOW_WIDTH-BALL_SIZE) or ball_x < BALL_SIZE:
  11. ball_dx = -ball_dx
  12. ball_x += ball_dx;
  13. elif ball_y > (WINDOW_HEIGHT-BALL_SIZE) or ball_y < BALL_SIZE:
  14. ball_dy = -ball_dy
  15. ball_y += ball_dy
  16. # 挡板的运动
  17. if paddle_move_left:
  18. paddle['rect'].left -= 8
  19. if paddle['rect'].left < 0:
  20. paddle['rect'].left = 0
  21. if paddle_move_right:
  22. paddle['rect'].left += 8
  23. if paddle['rect'].left > WINDOW_WIDTH-PADDLE_WIDTH:
  24. paddle['rect'].left = WINDOW_WIDTH-PADDLE_WIDTH
  25. # 绘制过程
  26. windowSurface.fill(BACKGROUND_COLOR)
  27. # 绘制挡板
  28. pygame.draw.rect(windowSurface, paddle['color'], paddle['rect'])
  29. # 绘制小球
  30. pygame.draw.circle(windowSurface, BALL_COLOR, (ball_x, ball_y),
  31. BALL_SIZE, 0)
  32. # 绘制砖块
  33. cur_x = BLOCK_ORIGIN_X
  34. cur_y = BLOCK_ORIGIN_Y
  35. for row in range(NUM_BLOCK_ROWS):
  36. cur_x = BLOCK_ORIGIN_X
  37. for col in range(NUM_BLOCK_COLUMNS):
  38. print(blocks[row][col])
  39. if (blocks[row][col] == 1):
  40. pygame.draw.rect(windowSurface, BLOCK_COLOR,
  41. (cur_x, cur_y, BLOCK_WIDTH, BLOCK_HEIGHT))
  42. cur_x += BLOCK_X_GAP
  43. cur_y += BLOCK_Y_GAP


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

6. 游戏流程和控制逻辑

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

1)把砖块打破

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

3)生命用完了则Game Over

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

    

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


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

2012-12-1      01:28
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/1002504
推荐阅读
相关标签
  

闽ICP备14008679号