【Python编程:从入门到实践】第十三章练习题

向右看齐 2023-06-23 02:52 203阅读 0赞

13-1 星星 :找一幅星星图像,并在屏幕上显示一系列整齐排列的星星。
13-2 更逼真的星星 :为让星星的分布更逼真,可随机地放置星星。

合并为一个程序“满天星”,效果图如下:watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpbmcwOTY0_size_16_color_FFFFFF_t_70

代码:

settings.py(定义一些必须的基本属性和初始值)

  1. class Settings():
  2. def __init__(self):
  3. self.screen_width = 1200
  4. self.screen_height = 600

star.py(为了实现星星大小不一,使用smoothscale进行缩放,缩放值随机)

  1. import pygame
  2. from pygame.sprite import Sprite
  3. from random import randint
  4. class Star(Sprite):
  5. def __init__(self):
  6. # 继承父类
  7. super(Star, self).__init__()
  8. # 加载图片
  9. self.image = pygame.image.load('../images/star.png')
  10. # 平滑缩放到(宽,高)
  11. random_number = randint(10, 30)
  12. self.image = pygame.transform.smoothscale(self.image, (random_number, random_number))
  13. self.rect = self.image.get_rect()

game_functions.py(可修改数字5来控制星星显示疏密)

  1. from star import Star
  2. from random import randint
  3. def create_stars(settings, stars):
  4. star = Star()
  5. # 数字5(越大越少)控制疏密
  6. number_stars_x = int(settings.screen_width / (5 * star.rect.width))
  7. number_stars_y = int(settings.screen_height / (5 * star.rect.height))
  8. for number_y in range(number_stars_y):
  9. for number_x in range(number_stars_x):
  10. random_number_x = randint(0, settings.screen_width)
  11. random_number_y = randint(0, settings.screen_height)
  12. star = Star()
  13. # # 规则排列
  14. # star.rect.x = 2 * star.rect.width * number_x
  15. # star.rect.y = 2 * star.rect.height * number_y
  16. # 不规则排列
  17. star.rect.x = random_number_x
  18. star.rect.y = random_number_y
  19. stars.add(star)

babysbreath.py(主函数)

  1. import pygame
  2. import sys
  3. from pygame.sprite import Group
  4. from settings import Settings
  5. import game_functions as gf
  6. def run_game():
  7. pygame.init()
  8. settings = Settings()
  9. screen = pygame.display.set_mode((settings.screen_width, settings.screen_height))
  10. # # 全屏显示
  11. # screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
  12. pygame.display.set_caption('满天星')
  13. stars = Group()
  14. gf.create_stars(settings, stars)
  15. stars.draw(screen)
  16. while True:
  17. # 需加事件,不然秒退
  18. for event in pygame.event.get():
  19. if event.type == pygame.QUIT:
  20. sys.exit()
  21. # 让最近绘制的屏幕可见
  22. pygame.display.flip()
  23. run_game()

13-4 连绵细雨 :修改为完成练习 13-3 而编写的代码,使得一行雨滴消失在屏幕底端后,屏幕顶端又出现一行新雨滴,并开始往下落。

优化为“下雨天”,效果如下图:

20191217095047587.gif

代码:

settings.py(定义一些必须的基本属性和初始值)

  1. class Settings():
  2. def __init__(self):
  3. self.screen_width = 1200
  4. self.screen_height = 600

raindrop.py(为了效果更逼真,雨滴落下速度使用随机数random_number / 5)

  1. import pygame
  2. from pygame.sprite import Sprite
  3. from random import randint
  4. class Raindrop(Sprite):
  5. def __init__(self):
  6. # 继承父类
  7. super(Raindrop, self).__init__()
  8. # 加载图片
  9. self.image = pygame.image.load('../images/raindrop.png')
  10. # 平滑缩放到(宽,高)
  11. random_number = randint(10, 30)
  12. self.image = pygame.transform.smoothscale(self.image, (random_number, random_number))
  13. self.rect = self.image.get_rect()
  14. def update(self):
  15. """向下移动雨滴"""
  16. random_number = randint(1, 10)
  17. self.rect.y += random_number / 5

game_functions.py(使用random_number_y = randint(0, 300),让雨从半空飘落)

  1. from raindrop import Raindrop
  2. from random import randint
  3. def create_raindrops(settings, raindrops):
  4. """创建很多雨滴"""
  5. raindrop = Raindrop()
  6. # 数字4(越大越少)控制稀疏
  7. number_raindrops_x = int(settings.screen_width / (4 * raindrop.rect.width))
  8. number_raindrops_y = int(settings.screen_height / (4 * raindrop.rect.height))
  9. for number_y in range(number_raindrops_y):
  10. for number_x in range(number_raindrops_x):
  11. create_raindrop(raindrops)
  12. def update_raindrops(screen, raindrops):
  13. """更新所有雨滴的位置"""
  14. screen_rect = screen.get_rect()
  15. for raindrop in raindrops.sprites():
  16. if raindrop.rect.bottom >= screen_rect.bottom:
  17. raindrops.remove(raindrop)
  18. create_raindrop(raindrops)
  19. raindrops.update()
  20. def create_raindrop(raindrops):
  21. """创建单个雨滴"""
  22. random_number_x = randint(0, 1200)
  23. random_number_y = randint(0, 300)
  24. raindrop = Raindrop()
  25. # 不规则排列
  26. raindrop.rect.x = random_number_x
  27. raindrop.rect.y = random_number_y
  28. raindrops.add(raindrop)

rain.py(主函数)

  1. import pygame
  2. import sys
  3. from pygame.sprite import Group
  4. from settings import Settings
  5. import game_functions as gf
  6. def run_game():
  7. pygame.init()
  8. settings = Settings()
  9. screen = pygame.display.set_mode((settings.screen_width, settings.screen_height))
  10. pygame.display.set_caption('下雨天')
  11. raindrops = Group()
  12. gf.create_raindrops(settings, raindrops)
  13. while True:
  14. # 设置背景色(不设置会导致雨滴整个拖下来)
  15. screen.fill((125, 125, 125))
  16. # 需加事件,不然秒退
  17. for event in pygame.event.get():
  18. if event.type == pygame.QUIT:
  19. sys.exit()
  20. gf.update_raindrops(screen, raindrops)
  21. raindrops.draw(screen)
  22. # 让最近绘制的屏幕可见
  23. pygame.display.flip()
  24. run_game()

13-5 抓球 :创建一个游戏,在屏幕底端放置一个玩家可左右移动的角色。让一个球出现在屏幕顶端,且水平位置是随机的,并让这个球以固定的速度往下落。如果角色与球发生碰撞(表示将球抓住了),就让球消失。每当角色抓住球或球因抵达屏幕底端而消失后,都创建一个新球。
13-6 游戏结束 :在为完成练习 13-5 而编写的代码中,跟踪玩家有多少次未将球接着。在未接着球的次数到达三次后,结束游戏。

合并为一个“抓球游戏”,效果图如下(详细查看https://jingyan.baidu.com/article/597a0643bcb5a5712a524311.html):

2019121710092822.gif

代码:

settings.py(定义一些必须的基本属性和初始值)

  1. class Settings():
  2. def __init__(self):
  3. self.screen_width = 1200
  4. self.screen_height = 600
  5. self.bg_color = (230, 230, 230)
  6. # 人移动速度
  7. self.people_move_speed = 1.5
  8. # 球落下速度
  9. self.ball_drop_speed = 0.5
  10. #统计信息设置
  11. # 游戏得分
  12. self.game_score = 0
  13. # 接到一个球多少分
  14. self.ball_score = 10
  15. # 丢失多少球结束游戏
  16. self.ball_miss_number = 3

ball.py(因为有两处用到球图片,只是大小不一致,定义一个缩放函数scale)

  1. import pygame
  2. from pygame.sprite import Sprite
  3. class Ball(Sprite):
  4. def __init__(self, settings):
  5. super(Ball, self).__init__()
  6. self.settings = settings
  7. self.image = pygame.image.load('../images/ball.png')
  8. self.rect = self.image.get_rect()
  9. self.center = float(self.rect.centerx)
  10. def scale(self, multiple):
  11. # 图片缩放
  12. self.image = pygame.transform.smoothscale(self.image, (multiple, multiple))
  13. def update(self):
  14. # 球落下
  15. self.center += self.settings.ball_drop_speed
  16. self.rect.centery = self.center

people.py(self.center = float(self.rect.centerx),因为设置的移动速度存在小数位,这里要加上float,不然效果会有问题)

  1. import pygame
  2. class People():
  3. def __init__(self, settings, screen):
  4. self.settings = settings
  5. self.screen = screen
  6. self.image = pygame.image.load('../images/people.png')
  7. self.rect = self.image.get_rect()
  8. # 人初始位置
  9. self.screen_rect = self.screen.get_rect()
  10. self.rect.centerx = self.screen_rect.centerx
  11. self.rect.bottom = self.screen_rect.bottom
  12. # 在飞船的属性 center 中存储小数值(不然会导致小数位不起作用)
  13. self.center = float(self.rect.centerx)
  14. # 移动标志
  15. self.moving_right = False
  16. self.moving_left = False
  17. def update(self):
  18. """ 根据移动标志调整人的位置 """
  19. # 更新人的 center 值,而不是 rect
  20. if self.moving_right and self.rect.right < self.screen_rect.right:
  21. self.center += self.settings.people_move_speed
  22. if self.moving_left and self.rect.left > 0:
  23. self.center -= self.settings.people_move_speed
  24. # 根据 self.center 更新 rect 对象
  25. self.rect.centerx = self.center
  26. def blitme(self):
  27. """绘制人"""
  28. # blit绘制到缓冲区,不显示于屏幕(需要flip才能显示到屏幕)
  29. self.screen.blit(self.image, self.rect)

button.py

  1. import pygame.font
  2. class Button():
  3. def __init__(self, screen, msg):
  4. """初始化按钮的属性"""
  5. self.screen = screen
  6. self.screen_rect = screen.get_rect()
  7. # 设置按钮的尺寸和其他属性
  8. self.width, self.height = 150, 50
  9. self.button_color = (125, 125, 125)
  10. self.text_color = (255, 255, 255)
  11. self.font = pygame.font.SysFont(None, 30)
  12. # 创建按钮的rect对象,并使其居中
  13. self.rect = pygame.Rect(0, 0, self.width, self.height)
  14. # 按钮的标签只需创建一次
  15. self.prep_msg(msg)
  16. def prep_msg(self, msg):
  17. """将msg渲染为图像,并使其在按钮上居中"""
  18. self.rect.center = self.screen_rect.center
  19. self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)
  20. self.msg_image_rect = self.msg_image.get_rect()
  21. self.msg_image_rect.center = self.rect.center
  22. def draw_button(self):
  23. # 绘制一个用颜色填充的按钮,再绘制文本
  24. self.screen.fill(self.button_color, self.rect)
  25. self.screen.blit(self.msg_image, self.msg_image_rect)

scoreboard.py(由于绘制左上角的球图片缩小了,所以球之间的间距也要按比例缩小“ball.rect.x”)

  1. import pygame
  2. from pygame.sprite import Group
  3. from ball import Ball
  4. class Scoreboard():
  5. """docstring for Scoreboard"""
  6. def __init__(self, settings, screen):
  7. self.settings = settings
  8. self.screen = screen
  9. self.screen_rect = screen.get_rect()
  10. # 球缩放值
  11. self.scaleValue = 20
  12. # 显示得分信息时使用的字体设置
  13. self.text_color = (30, 30, 30)
  14. self.font = pygame.font.SysFont(None, 48)
  15. self.prep_score()
  16. self.prep_balls()
  17. def prep_score(self):
  18. """将得分转换为渲染的图像"""
  19. rounded_score = int(round(self.settings.game_score, -1))
  20. score_str = '{:,}'.format(rounded_score)
  21. self.score_image = self.font.render(score_str, True, self.text_color, self.settings.bg_color)
  22. self.score_rect = self.score_image.get_rect()
  23. self.score_rect.right = self.screen_rect.right - 10
  24. self.score_rect.top = 10
  25. def prep_balls(self):
  26. # 显示还能丢失多少球
  27. self.balls = Group()
  28. for number in range(self.settings.ball_miss_number):
  29. ball = Ball(self.settings)
  30. # 缩放球大小并赋值位置
  31. ball.scale(self.scaleValue)
  32. ball.rect.x = 10 + ball.rect.width * (self.scaleValue / ball.rect.width) * number
  33. ball.rect.y = 10
  34. self.balls.add(ball)
  35. def show_score(self):
  36. self.balls.draw(self.screen)
  37. self.screen.blit(self.score_image, self.score_rect)

game_functions.py

  1. import sys
  2. import pygame
  3. from ball import Ball
  4. from button import Button
  5. from random import randint
  6. # 事件
  7. def check_events(people):
  8. """ 响应按键和鼠标事件 """
  9. for event in pygame.event.get():
  10. if event.type == pygame.QUIT:
  11. sys.exit()
  12. elif event.type == pygame.KEYDOWN:
  13. check_keydown_events(event, people)
  14. elif event.type == pygame.KEYUP:
  15. check_keyup_events(event, people)
  16. def check_keydown_events(event, people):
  17. """ 响应按键 """
  18. if event.key == pygame.K_RIGHT:
  19. people.moving_right = True
  20. elif event.key == pygame.K_LEFT:
  21. people.moving_left = True
  22. elif event.key == pygame.K_q:
  23. sys.exit()
  24. def check_keyup_events(event, people):
  25. """ 响应松开 """
  26. if event.key == pygame.K_RIGHT:
  27. people.moving_right = False
  28. elif event.key == pygame.K_LEFT:
  29. people.moving_left = False
  30. # 球
  31. def update_balls(settings, balls, people, screen, scoreboard):
  32. """更新球的位置"""
  33. # 创建球(一直1个)
  34. if len(balls) == 0:
  35. create_ball(settings, balls, screen)
  36. # 球碰撞到人,就消失
  37. if pygame.sprite.spritecollideany(people, balls):
  38. balls.empty()
  39. settings.game_score += settings.ball_score
  40. scoreboard.prep_score()
  41. # 球到底则消失
  42. screen_rect = screen.get_rect()
  43. for ball in balls.sprites():
  44. if ball.rect.bottom >= screen_rect.bottom:
  45. balls.remove(ball)
  46. # 减少可落下的数量并更新显示球数量
  47. settings.ball_miss_number -= 1
  48. scoreboard.prep_balls()
  49. # 当球未接住的数据达到设置的数量,则绘制“Game Over”并结束游戏
  50. if settings.ball_miss_number == 0:
  51. button = Button(screen, 'Game Over')
  52. button.draw_button()
  53. return
  54. balls.update()
  55. def create_ball(settings, balls, screen):
  56. """创建单个球"""
  57. ball = Ball(settings)
  58. # 球初始位置(顶部,水平位置随机)
  59. screen_rect = screen.get_rect()
  60. number_x = randint(0, settings.screen_width)
  61. ball.rect.centerx = number_x
  62. ball.rect.top = screen_rect.top
  63. balls.add(ball)

catchball.py(主函数)

  1. import pygame
  2. from pygame.sprite import Group
  3. from settings import Settings
  4. import game_functions as gf
  5. from people import People
  6. from scoreboard import Scoreboard
  7. def run_game():
  8. pygame.init()
  9. settings = Settings()
  10. # screen = pygame.display.set_mode((settings.screen_width, settings.screen_height))
  11. # 全屏显示
  12. screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
  13. pygame.display.set_caption('抓球')
  14. # 创建人和球
  15. people = People(settings, screen)
  16. # 创建球的编组
  17. balls = Group()
  18. # 创建记分牌
  19. scoreboard = Scoreboard(settings, screen)
  20. while True:
  21. # 设置背景色
  22. screen.fill(settings.bg_color)
  23. # 检查玩家输入
  24. gf.check_events(people)
  25. # 更新人位置并绘制到屏幕
  26. people.update()
  27. people.blitme()
  28. # 更新球位置并绘制到屏幕
  29. gf.update_balls(settings, balls, people, screen, scoreboard)
  30. balls.draw(screen)
  31. # 显示得分
  32. scoreboard.show_score()
  33. # 让最近绘制的屏幕可见
  34. pygame.display.flip()
  35. run_game()

  Tips:所使用的图标可自行上“https://www.iconfont.cn/”查找。

发表评论

表情:
评论列表 (有 0 条评论,203人围观)

还没有评论,来说两句吧...

相关阅读