当前位置:   article > 正文

python小游戏----外星人入侵_python外星人入侵代码

python外星人入侵代码

源代码:

AlienInvasion/game at main · CrashBugger/AlienInvasion (github.com)

本文来自作者对《python编程-从入门到实践》的学习记录,刚刚入门python,小白一个,若有错误,欢迎大佬指出。

图片资源:

just nobibi,show me the code!话不多说,开始项目。

1.创建pygame窗口响应用户输出

导包

  1. import pygame
  2. import sys
  3. import settings

接下来

开始进行初步准备sssssssss

  1. def run_game():
  2. # 初始化游戏并创建一个屏幕对象
  3. pygame.init()
  4. screen = pygame.display.set_mode((1200, 800))
  5. pygame.display.set_caption("Alien Invasion")
  6. # 游戏主循环
  7. while True:
  8. # 监视键盘和鼠标时间
  9. for event in pygame.event.get():
  10. if event == pygame.QUIT:
  11. sys.exit()
  12. # 让最近的绘制的屏幕可见
  13. pygame.display.flip()
  •  其中pygame.init()方法初始化背景设置
  • pygame.display.set_mode()创建一个名为screen的窗口对象,以后我们将在这里面绘制图形元素,需要传入一个元组,表示窗口的长高。screen是一个surface对象
  • while循环控制游戏进行,for循环侦听事件,pygame.event.get()方法拿到事件列表,当检测到用户离开时,系统退出
  • display.flip()方法让最近绘制的屏幕可见
    

2.设置背景色

先上代码

  1. def run_game():
  2. # 初始化游戏并创建一个屏幕对象
  3. pygame.init()
  4. screen = pygame.display.set_mode((1200, 800))
  5. pygame.display.set_caption("Alien Invasion")
  6. # shezhibeijingse
  7. bg_color = (230, 230, 230)
  8. # 游戏主循环
  9. while True:
  10. # 监视键盘和鼠标时间
  11. for event in pygame.event.get():
  12. if event == pygame.QUIT:
  13. sys.exit()
  14. # 每次循环重新绘制屏幕
  15. screen.fill(bg_color)
  16. # 让最近的绘制的屏幕可见
  17. pygame.display.flip()
  • 创建一个元组bg_color存储RGB颜色,接下来在主循环中在screen中填充颜色,

3.创建设置类

 这一步对前一步进行优化,创建一个settings类,用来保存我们的设置

  1. class Settings():
  2. def __init__(self):
  3. self.screen_width = 1200
  4. self.screen_height = 800
  5. self.bg_color = (230, 230, 230)

接下来回到主方法创建这个类的实例进行设置

  1. def run_game():
  2. # 初始化游戏,并创建一个屏幕对象
  3. pygame.init()
  4. ai_settings = settings.Settings()
  5. screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
  6. pygame.display.set_caption("Ailien Invasion")
  7. # bg_color = (230, 230, 230)
  8. while True:
  9. # 监听事件
  10. for event in pygame.event.get():
  11. if event.type == pygame.QUIT:
  12. sys.exit()
  13. # 每次循环重置屏幕
  14. screen.fill(ai_settings.bg_color)
  15. # 最近绘制的屏幕可见
  16. pygame.display.flip()

4.创建ship类并绘制飞船

创建一个新的文件夹,命名为images,将ship.bmp放进去,接下来创建ship类

  1. import pygame
  2. class Ship():
  3. def __init__(self, screen):
  4. self.screen = screen
  5. # 加载飞船图像并获取外接矩形
  6. self.image = pygame.image.load("D:\PyCharm\Code\project\game\images\ship.bmp")
  7. self.rect = self.image.get_rect()
  8. self.screen_rect = screen.get_rect()
  9. # 将飞船放在屏幕底部中央
  10. self.rect.centerx = self.screen_rect.centerx
  11. self.rect.bottom = self.screen_rect.bottom
  12. def blitme(self):
  13. """在指定位置绘制飞船"""
  14. self.screen.blit(self.image, self.rect)
  • pygame可以像处理矩形一样处理游戏元素,处理rect对象,可以使用矩形中心xy坐标和矩形四角
  • 要将飞船显示在中央,需要设置rect对象的center,centerx或centery;如果要将飞船与边缘对其,可以设置其top,bottom,left,right属性;如果要调整坐标,需要设置其x,y属性,注意原点在左上角。
  • 在主方法中加入飞船
  1. def run_game():
  2. # 初始化游戏,并创建一个屏幕对象
  3. pygame.init()
  4. ai_settings = settings.Settings()
  5. screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
  6. pygame.display.set_caption("Ailien Invasion")
  7. # 创建一艘飞船
  8. ship = Ship(screen)
  9. while True:
  10. # 监听事件
  11. for event in pygame.event.get():
  12. if event.type == pygame.QUIT:
  13. sys.exit()
  14. # 每次循环重置屏幕
  15. screen.fill(ai_settings.bg_color)
  16. ship.blitme()
  17. # 最近绘制的屏幕可见
  18. pygame.display.flip()

 5.重构模块geme_functions

  • 我们将游戏中的各个控制方法抽离到一个专门的模块
  • game_functions.py
  1. import sys
  2. import pygame
  3. import ship
  4. from game import settings
  5. def check_events():
  6. """响应按键和鼠标事件"""
  7. for event in pygame.event.get():
  8. if event.type == pygame.QUIT:
  9. sys.exit()
  10. def update_screen(ai_settings: settings.Settings, screen, ship: ship.Ship):
  11. """更新屏幕上的图像,并切换到新屏幕"""
  12. # 每次循环chonghuipingmu
  13. screen.fill(ai_settings.bg_color)
  14. ship.blitme()
  15. # 最近绘制的屏幕可见
  16. pygame.display.filp()

 这些都是原本主循环中的方法,现在整合到一个模块

主方法在修改一下

先把刚创建的模块导包

import game_functions as gf
  1. def run_game():
  2. # 初始化游戏,并创建一个屏幕对象
  3. pygame.init()
  4. ai_settings = settings.Settings()
  5. screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
  6. pygame.display.set_caption("Ailien Invasion")
  7. # 创建一艘飞船
  8. ship = Ship(screen)
  9. while True:
  10. # 监听事件
  11. gf.check_events()
  12. # 每次循环重置屏幕
  13. gf.update_screen(ai_settings, screen, ship)

6.驾驶飞船

先在ship类中新加一个属性moving_right=False,当检测到移动时,置位true,并新定义update方法,更新飞船位置

  • Ship类
  1. def __init__(self, screen):
  2. self.screen = screen
  3. # 加载飞船图像并获取外接矩形
  4. self.image = pygame.image.load("D:\PyCharm\Code\project\game\images\ship.bmp")
  5. self.rect = self.image.get_rect()
  6. self.screen_rect = screen.get_rect()
  7. # 将飞船放在屏幕底部中央
  8. self.rect.centerx = self.screen_rect.centerx
  9. self.rect.bottom = self.screen_rect.bottom
  10. # 移动标志
  11. self.moving_right = False
  12. def blitme(self):
  13. """在指定位置绘制飞船"""
  14. self.screen.blit(self.image, self.rect)
  15. def update(self):
  16. if self.moving_right:
  17. self.rect.centerx += 1

我们在game_functions.py的check_events方法中加入检测用户键盘的代码

  • game_functions.py
  1. def check_events(ship: ship.Ship):
  2. """响应按键和鼠标事件"""
  3. for event in pygame.event.get():
  4. if event.type == pygame.QUIT:
  5. sys.exit()
  6. # 用户按下键盘
  7. elif event.type == pygame.KEYDOWN:
  8. if event.key == pygame.K_RIGHT:
  9. ship.moving_right = True
  10. elif event.type == pygame.KEYUP:
  11. if event.key == pygame.K_RIGHT:
  12. ship.moving_right = False

当用按下键盘时,我们在event检测其type属性,若为keydown,再进一步判断是否为向右键,并将ship类中的moving——righ属性置为true,当玩家抬起右键时,检测到keyup,将其置为false,

并在主方法中不断调用ship类的update方法

  • 主方法
  1. def run_game():
  2. # 初始化游戏,并创建一个屏幕对象
  3. pygame.init()
  4. ai_settings = settings.Settings()
  5. screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
  6. pygame.display.set_caption("Ailien Invasion")
  7. # 创建一艘飞船
  8. ship = Ship(screen)
  9. while True:
  10. # 监听事件
  11. gf.check_events(ship)
  12. # 更新
  13. ship.update()
  14. # 每次循环重置屏幕
  15. gf.update_screen(ai_settings, screen, ship)

7.调整飞船速度并限制飞船移动边界

  • 在settings类中新加属性self.ship_speed_factor用于控制飞船速度
  • 接下来在ship的方法init方法传入settings对象,并在update方法中用他的属性修改坐标,因为rect只存储整数部分的值,所以为了精细控制速度,我们用float方法返回rect.centerx保存到center属性,并在update方法对center修改,最后再用center覆盖centerx。
  • 判断边界只需要在update方法中判断当前rect的left属性和right属性是否超出边界。
Ship类
  1. class Ship():
  2. def __init__(self, screen, ai_settings: Settings):
  3. self.screen = screen
  4. # 加载飞船图像并获取外接矩形
  5. self.image = pygame.image.load("D:\PyCharm\Code\project\game\images\ship.bmp")
  6. self.rect = self.image.get_rect()
  7. self.screen_rect = screen.get_rect()
  8. # 将飞船放在屏幕底部中央
  9. self.rect.centerx = self.screen_rect.centerx
  10. self.rect.bottom = self.screen_rect.bottom
  11. # 移动标志
  12. self.moving_right = False
  13. self.moving_left = False
  14. # 飞船设置
  15. self.ai_settings = ai_settings
  16. # 在飞船的center属性中存储小数值
  17. self.center = float(self.rect.centerx)
  18. def blitme(self):
  19. """在指定位置绘制飞船"""
  20. self.screen.blit(self.image, self.rect)
  21. def update(self):
  22. # 加上边界判断
  23. if self.moving_right and self.rect.right < self.screen_rect.right:
  24. self.center += self.ai_settings.ship_speed_factor
  25. if self.moving_left and self.rect.left > 0:
  26. self.center -= self.ai_settings.ship_speed_factor
  27. # 覆盖
  28. self.rect.centerx = self.center

8.重构check_functions

  1. def check_keydown_events(event, ship):
  2. if event.key == pygame.K_RIGHT:
  3. ship.moving_right = True
  4. elif event.key == pygame.K_LEFT:
  5. ship.moving_left = True
  6. def check_keyup_events(event, ship):
  7. if event.key == pygame.K_RIGHT:
  8. ship.moving_right = False
  9. elif event.key == pygame.K_LEFT:
  10. ship.moving_left = False
  11. def check_events(ship: ship.Ship):
  12. """响应按键和鼠标事件"""
  13. for event in pygame.event.get():
  14. if event.type == pygame.QUIT:
  15. sys.exit()
  16. # 用户按下键盘
  17. elif event.type == pygame.KEYDOWN:
  18. check_keydown_events(event, ship)
  19. elif event.type == pygame.KEYUP:
  20. check_keyup_events(event, ship)
  • 提取出两个方法,如图

9.创建子弹类并加入编组

bullet.py

  1. import pygame
  2. from pygame.sprite import Sprite
  3. from game.settings import Settings
  4. from game.ship import Ship
  5. class Bullet(Sprite):
  6. def __init__(self, ai_settings: Settings, screen, ship: Ship):
  7. """在飞船所在位置创建子弹"""
  8. super().__init__()
  9. self.screen = screen
  10. # 在(0.0)处创建一个子弹矩形
  11. self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
  12. # 修改位置
  13. self.rect.centerx = ship.rect.centerx
  14. self.rect.top = ship.rect.top
  15. # 存储小数表示位置
  16. self.y = float(self.rect.y)
  17. self.color = ai_settings.bullet_color
  18. self.speed_factor = ai_settings.bullet_speed_factor
  19. def update(self):
  20. """向上移动子弹"""
  21. # 更新y坐标
  22. self.y -= self.speed_factor
  23. # 覆盖
  24. self.rect.y = self.y
  25. def draw_bullet(self):
  26. """在屏幕上绘制子弹"""
  27. pygame.draw.rect(self.screen, self.color, self.rect)
  • 我们继承sprite类,可以将子弹编组,同时操作编组中的元素。并传入settings对象ship对象和screen对象
  • 用rect存储子弹矩形,并设置其centerx和top属性,让它与飞船相同
  • 跟上一个相同的原因,我们用float()精细调整子弹y坐标

我们在主方法导包并创建Group()实例,并将其传入while循环中的三个方法

from pygame.sprite import Group
  1. # 初始化游戏,并创建一个屏幕对象
  2. pygame.init()
  3. ai_settings = settings.Settings()
  4. screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
  5. pygame.display.set_caption("Ailien Invasion")
  6. # 创建一艘飞船
  7. ship = Ship(screen, ai_settings)
  8. # 创建用于存储子弹的编组
  9. bullets = Group()
  10. while True:
  11. # 监听事件
  12. gf.check_events(ship, bullets)
  13. # 更新
  14. ship.update()
  15. # 更新子弹位置
  16. bullets.update()
  17. # 每次循环重置屏幕
  18. gf.update_screen(ai_settings, screen, ship, bullets)
  • 编组的作用就是存储子弹,并且当调用update()方法时,自动对里面的每个子弹调用update方法,bullets.update()将被每颗子弹调用

10.Fire!开火

  • 这里期望玩家按空格键可以完成开火
  • 我们在functions对check_keydown方法加入对空格的判断若判断到,则在编组中新加入子弹;并在update_screen方法中重绘子弹,注意重绘子弹应在screen.flip()方法调用之前
  • 注意修改方法的参数
  1. class Bullet(Sprite):
  2. def __init__(self, ai_settings: Settings, screen, ship: Ship):
  3. """在飞船所在位置创建子弹"""
  4. super().__init__()
  5. self.screen = screen
  6. # 在(0.0)处创建一个子弹矩形
  7. self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
  8. # 修改位置
  9. self.rect.centerx = ship.rect.centerx
  10. self.rect.top = ship.rect.top
  11. # 存储小数表示位置
  12. self.y = float(self.rect.y)
  13. self.color = ai_settings.bullet_color
  14. self.speed_factor = ai_settings.bullet_speed_factor
  15. def update(self):
  16. """向上移动子弹"""
  17. # 更新y坐标
  18. self.y -= self.speed_factor
  19. # 覆盖
  20. self.rect.y = self.y
  21. def draw_bullet(self):
  22. """在屏幕上绘制子弹"""
  23. pygame.draw.rect(self.screen, self.color, self.rect)
  • 成功开火后,有个问题,那些飞出屏幕外的子弹,仍然留在内存中,这样越积越多,会让我们的游戏慢的龟爬一样,所以在主方法while循环中添加一个删除子弹的方法,判断子弹的bottom属性是否小于等于0,成立则从编组中删除掉
  1. while True:
  2. # 监听事件
  3. gf.check_events(ai_settings, screen, ship, bullets)
  4. # 更新
  5. ship.update()
  6. # 更新子弹位置
  7. bullets.update()
  8. # 删除已经消失的子弹
  9. for bullet in bullets.copy():
  10. if bullet.rect.bottom <= 0:
  11. bullets.remove(bullet)
  12. # 每次循环重置屏幕
  13. gf.update_screen(ai_settings, screen, ship, bullets)
  • 下来我们在对代码进行优化,创建update_bullets函数和fire_bullets来将原本开火和更新的代码抽离
  • games_functions.py
    1. def update_bullets(bullets: Bullet):
    2. """更新子弹未位置"""
    3. # 更新位置
    4. bullets.update()
    5. # 删除已经消失的子弹
    6. for bullet in bullets.copy():
    7. if bullet.rect.bottom <= 0:
    8. bullets.remove(bullet)
    9. def fire_bullets(ai_settings: Settings, screen: surface, ship: ship.Ship, bullets: Bullet):
    10. # 若子弹数量小于3,创建一颗新子弹,
    11. if len(bullets) < ai_settings.bullets_allowed:
    12. new_bullet = Bullet(ai_settings, screen, ship)
    13. bullets.add(new_bullet)

    修改其中的keydown函数

    1. def check_keydown_events(event, ai_settings: Settings, screen, ship, bullets: Bullet):
    2. if event.key == pygame.K_RIGHT:
    3. ship.moving_right = True
    4. elif event.key == pygame.K_LEFT:
    5. ship.moving_left = True
    6. elif event.key == pygame.K_SPACE:
    7. fire_bullets(ai_settings, screen, ship, bullets)

    11.创建外星人

  • 我们首先改变一下游戏退出的方式,按下Q键即可退出,在game_functions.py中的key_down方法加上下面一条

    1. elif event.key == pygame.K_q:
    2. sys.exit(1)

    创建外星人类

  1. import pygame
  2. from pygame import surface
  3. from pygame.sprite import Sprite
  4. from game.settings import Settings
  5. class Alien(Sprite):
  6. """表示单个外星人的类"""
  7. def __init__(self, ai_settings: Settings, screen: surface):
  8. # 初始化外星人并设置其起始位置
  9. super(Alien, self).__init__()
  10. self.screen = screen
  11. self.ai_settings = ai_settings
  12. # 加载外星人图像,设置其rect属性
  13. self.image = pygame.image.load(r"D:\PyCharm\Code\project\game\images\alien.bmp")
  14. self.rect = self.image.get_rect()
  15. # 每个外星人初始位置都在屏幕左上角附近
  16. self.rect.x = self.rect.width
  17. self.rect.y = self.rect.height
  18. # 存储外星人的准确位置
  19. self.x = float(self.rect.x)
  20. def blitme(self):
  21. """在指定位置绘制外星人"""
  22. self.screen.blit(self.image, self.rect)
  • 讲解同ship类一样,不在赘述
  • 接下来我们要将外星人在图像上画出来,需要在主方法中创建一个实例
    1. # 创建外星人实例
    2. alien = Alien(ai_settings, screen)

    并在game_functions中修改update_screen方法

  • game_functions.py

    1. def update_screen(ai_settings: Settings, screen, ship: ship.Ship, alien: Alien, bullets: Bullet):
    2. """更新屏幕上的图像,并切换到新屏幕"""
    3. # 每次循环重绘屏幕
    4. screen.fill(ai_settings.bg_color)
    5. ship.blitme()
    6. # 绘制外星人
    7. alien.blitme()
    8. # 重绘子弹
    9. for bullet in bullets.sprites():
    10. bullet.draw_bullet()
    11. # 最近绘制的屏幕可见
    12. pygame.display.flip()
  •  调用个blitme方法即可,注意还需要在flip方法调用之前
  • 尝试成功,接下来我们要创建一行外星人
  • 在game_functions.py中加入如下方法
  • 在主方法中循环之前加入
    1. # 创建外星人群
    2. aliens = Group()
    3. gf.create_fleet(ai_settings, screen, aliens)

    aliens是一个空的编组,前面介绍过,编组可以对其中的每个元素调用方法,并将它传入create_fleet()方法,这个方法在game_functions.py中定义

  • game_functions.py

  1. def create_fleet(ai_settings: Settings, screen, aliens: Group):
  2. """创建外星人群"""
  3. # 创建一个外星人,并计算一行可以容纳多少个外星人
  4. alien: Alien = Alien(ai_settings, screen)
  5. alien_width = alien.rect.width
  6. available_space_x = ai_settings.screen_width - 2 * alien_width
  7. # 外星人间距为外星人宽度
  8. number_aliens_x = int(available_space_x / (2 * alien_width))
  9. # 创建第一行外星人
  10. for alien_number in range(number_aliens_x):
  11. newalien = Alien(ai_settings, screen)
  12. newalien.x = alien_width + 2 * alien_width * alien_number
  13. newalien.rect.x = newalien.x
  14. aliens.add(newalien)
  • 首先计算一行可以容纳多少个外星人,间距我们设置为外星人的宽度,接下来在编组中加入新建的外星人

12.重构creat_fleet()

  1. def create_fleet(ai_settings: Settings, screen, aliens: Group):
  2. """创建外星人群"""
  3. alien = Alien(ai_settings, screen)
  4. number_aliens_x = get_number_aliens(ai_settings, alien.rect.width, )
  5. for alien_number in range(number_aliens_x):
  6. create_alien(ai_settings, screen, aliens, alien_number)
  7. def get_number_aliens(ai_settings: Settings, alien_width: int) -> int:
  8. """获取一行容纳的外星人数量"""
  9. available_space_x = ai_settings.screen_width - 2 * alien_width
  10. # 外星人间距为外星人宽度
  11. number_aliens_x = int(available_space_x / (2 * alien_width))
  12. return number_aliens_x
  13. def create_alien(ai_settings, screen, aliens: Group, alien_number):
  14. """创建一个外星人并放在当前行"""
  15. alien = Alien(ai_settings, screen)
  16. alien_width = alien.rect.width
  17. alien.x = alien_width + 2 * alien_width * alien_number
  18. alien.rect.x = alien.x
  19. aliens.add(alien)

将其中的几个功能提取出来

13.添加多行外星人

game_functions.py

  1. def get_number_rows(ai_settings: Settings, ship_height, alien_height) -> int:
  2. """计算能容纳多少行"""
  3. available_space_y = (ai_settings.screen_height - (3 * alien_height) - ship_height)
  4. number_rows = int(available_space_y / (2 * alien_height))
  5. return number_rows
  • 加入上述代码
  1. def create_fleet(ai_settings: Settings, screen, ship: ship.Ship, aliens: Group):
  2. """创建外星人群"""
  3. alien = Alien(ai_settings, screen)
  4. number_aliens_x = get_number_aliens(ai_settings, alien.rect.width)
  5. number_rows = get_number_rows(ai_settings, ship.rect.height, alien.rect.height)
  6. for alien_number in range(number_aliens_x):
  7. for alien_row in range(number_rows):
  8. create_alien(ai_settings, screen, aliens, alien_number, alien_row)
  9. def create_alien(ai_settings, screen, aliens: Group, alien_number, row_number):
  10. """创建一个外星人并放在当前行"""
  11. alien = Alien(ai_settings, screen)
  12. alien_width = alien.rect.width
  13. # 当前x
  14. alien.x = alien_width + 2 * alien_width * alien_number
  15. # 当前y
  16. alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
  17. alien.rect.x = alien.x
  18. aliens.add(alien)
  • 修改create_fleet方法和create_alien方法
  • create_alien中加入一个参数row_number,表示当前应该添加到第几行,并据此修改y坐标
  • create_fleet方法中for循环新加一层层数循环

14.外星人移动

首先在settings.py中添加设置参数

  • settings.py
  1. # 外星人设置
  2. self.alien_speed_factor = 0.5#外星人水平移动速度
  3. self.fleet_drop_speed = 10#外星人竖直移动速度
  4. self.fleet_direction = 1 #移动方向: 1为向右,-1向左
  •  Alien.py中加入下述代码
  1. def update(self):
  2. """向左向右移动外星人"""
  3. self.x += self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction
  4. self.rect.x = self.x
  5. def check_edges(self):
  6. """如果外星人到达边缘,返回True"""
  7. screen_rect = self.screen.get_rect()
  8. if self.rect.right >= screen_rect.right:
  9. return True
  10. elif self.rect.left <= 0:
  11. return True
  • game_functions.py中加入
  1. def change_fleet_direction(ai_settings, aliens):
  2. """将外星人整体下移,并改变他们方向"""
  3. for alien in aliens.sprites():
  4. alien.rect.y += ai_settings.fleet_drop_speed
  5. ai_settings.fleet_direction *= -1
  6. def check_fleet_edges(ai_settings: Settings, aliens):
  7. """有外星人到达边缘时采取相应的措施"""
  8. for alien in aliens.sprites():
  9. if alien.check_edges():
  10. change_fleet_direction(ai_settings, aliens)
  11. break
  12. def update_aliens(ai_settings, aliens):
  13. """检查是否有外星人位于屏幕边缘,并更新调整外星人位置"""
  14. check_fleet_edges(ai_settings, aliens)
  15. aliens.update()
  • update_aliens为我们对主方法提供的接口,上面两个为辅助函数
  • 主方法while中调用update_aliens方法
  1. # 更新aliens
  2. gf.update_aliens(ai_settings, aliens)

15.射杀外星人并生成新的外星人群

我们需要调用pygame.sprite.groupcollied方法,这个方法检测两个编组中的元素是否重合,重合的话进行处理,并返回一个字典,每个键值对为子弹-外星人。其中第一个True表示重合的话删除第一个编组中的元素,第二个true表示删除第二个编组中的元素。我们在更新子弹位置时调用这个方法,并增加主方法中的参数调用

  • 击杀外星人后,我们需要判断是否需要生成新的外星人,若编组为空,重新调用生成外星人的方法
  • game_functions.py
  1. def update_bullets(ai_settings, screen, ship, aliens: Alien, bullets: Sprite):
  2. """更新子弹未位置"""
  3. # 更新位置
  4. bullets.update()
  5. # 删除已经消失的子弹
  6. for bullet in bullets.copy():
  7. if bullet.rect.bottom <= 0:
  8. bullets.remove(bullet)
  9. check_bullet_alien_collision(ai_settings, screen, ship, aliens, bullets)
  10. def check_bullet_alien_collision(ai_settings, screen, ship, aliens, bullets):
  11. # 检查是否有子弹击中外星人
  12. collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
  13. # 更新外星人
  14. if len(aliens) == 0:
  15. bullets.empty()
  16. create_fleet(ai_settings, screen, ship, aliens)

16.Boom!!!飞船与外星人相撞

如果飞船与外星人相撞或者外星人到底部,我们让游戏重置,重新生成外星人,并将飞船居中

ship.py

  1. def center_ship(self):
  2. """让飞船居中"""
  3. self.center = self.screen_rect.centerx
  • 我们还需要将飞船的命数减一,为此我们新建一个GameStatus类,用于记录游戏状态信息
  • 在Settings.py中新加属性
  •    self.ship_limit = 3

  • GameStatus.py
    1. class GameStatus():
    2. """跟踪游戏的统计信息"""
    3. def __init__(self, ai_settings):
    4. """初始化统计的信息"""
    5. self.ai_settings = ai_settings
    6. self.reset_status()
    7. def reset_status(self):
    8. """初始化在游戏运行期间可能变化的信息"""
    9. self.ships_left = self.ai_settings.ship_limit

 game_functions.py

  1. def update_aliens(ai_settings, stats, screen, ship, bullets, aliens):
  2. """检查是否有外星人位于屏幕边缘,并更新调整外星人位置"""
  3. check_fleet_edges(ai_settings, aliens)
  4. aliens.update()
  5. # 检测外星人和飞船是否相撞
  6. if pygame.sprite.spritecollideany(ship, aliens):
  7. ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
  8. # 检查外星人是否撞到底部
  9. check_aliens_bottom(aliens, ai_settings, stats, screen, ship, bullets)
  10. def ship_hit(ai_settings: Settings, status: GameStatus, screen, ship: ship.Ship, aliens, bullets):
  11. """响应外星人撞到飞船"""
  12. # 将飞船数量ship_left减一
  13. status.ships_left -= 1
  14. # 清空外星人和子弹
  15. aliens.empty()
  16. bullets.empty()
  17. # 创建一群新的外星人,重置飞船
  18. create_fleet(ai_settings, screen, ship, aliens)
  19. ship.center_ship()
  20. # 暂停
  21. sleep(0.5)
  22. def check_aliens_bottom(aliens: Alien, ai_settings: Settings, stats: GameStatus,
  23. screen: Surface, ship: ship.Ship, bullets):
  24. """检查是否有外星人到达底部"""
  25. screen_rect = screen.get_rect()
  26. for alien in aliens:
  27. if alien.rect.bottom >= screen_rect.bottom:
  28. # 像飞船撞到飞船一样处理
  29. ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
  30. break

我们调用update_aliens方法时,顺便检查一下飞船与外星人是否相撞,通过

pygame.sprite.spritecollideany(ship, aliens)

方法,第一个参数为一个飞船对象,第二个参数为一个编组,

17.游戏结束

game_functions.py的__ini__t中加入

  1. # 游戏刚启动处于活动状态
  2. self.game_active = True
  • 这个属性让我们可以再玩家命数耗尽后置为False退出游戏。
  • 改动game_functions.py方法,加入判断
  1. def ship_hit(ai_settings: Settings, status: GameStatus, screen, ship: ship.Ship, aliens, bullets):
  2. """响应外星人撞到飞船"""
  3. # 将飞船数量ship_left减一
  4. if status.ships_left > 0:
  5. status.ships_left -= 1
  6. # 清空外星人和子弹
  7. aliens.empty()
  8. bullets.empty()
  9. # 创建一群新的外星人,重置飞船
  10. create_fleet(ai_settings, screen, ship, aliens)
  11. ship.center_ship()
  12. # 暂停
  13. sleep(0.5)
  14. else:
  15. status.game_active = False
  • 主方法的while循环改为
    1. while True:
    2. # 监听事件
    3. gf.check_events(ai_settings, screen, ship, bullets)
    4. if stats.game_active:
    5. # 更新
    6. ship.update()
    7. # 更新子弹
    8. gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
    9. # 更新aliens
    10. gf.update_aliens(ai_settings, stats, screen, ship, bullets, aliens)
    11. # 每次循环重置屏幕
    12. gf.update_screen(ai_settings, screen, ship, aliens, bullets)

    18.添加开始按钮

  • button.py
  1. import pygame.font
  2. class Button():
  3. def __init__(self, ai_settings: Settings, screen: Surface, msg):
  4. """初始化按钮的属性"""
  5. self.screen = screen
  6. self.screen_rect = screen.get_rect()
  7. # 设置按钮的尺寸和其他属性
  8. self.width, self.height = 200, 50
  9. self.button_color = (0, 255, 0)
  10. self.text_color = (255, 255, 255)
  11. self.font = pygame.font.SysFont(None, 48)
  12. # 创建按钮的rect对象,并使其居中
  13. self.rect = pygame.Rect(0, 0, self.width, self.height)
  14. self.rect.center = self.screen_rect.center
  15. # 按钮标签只需创建一次
  16. self.prep_msg(msg)
  • font属性中我们调用pygame.font()方法,None表示用默认字体,48指的是字体字号。为了让按钮在屏幕居中,我们创建一个rect对象,并让他居中
  • 接下来在新建一个方法prep_msg方法来处理按钮的渲染和绘制按钮的方法
  1. def prep_msg(self, msg):
  2. """将msg渲染为图像,并将其在按钮上居中"""
  3. self.msg_image = self.font.render(self, True, self.text_color, self.button_color)
  4. self.msg_image_rect = self.msg_image.get_rect()
  5. self.msg_image_rect.center = self.rect.center
  6. def draw_button(self):
  7. """绘制一个用颜色填充的按钮,在绘制文本"""
  8. self.screen.fill(self.button_color, self.rect)
  9. self.screen.blit(self.msg_image, self.msg_image_rect)
  • 其中的font.render方法将存储在msg中的文本转换为图像,并将其存储在msg_image中,其中的True参数表示开启抗锯齿功能,可以让文字边缘更光滑。接下来最后调通过rect调整按钮位置。
  • 接下来draw_button来绘制按钮。
  • game_functions.py的update_screen中加入判断游戏活动状态的if语句,若不在活动状态,绘制一个按钮
    1. def update_screen(ai_settings: Settings, screen, stats: GameStatus, ship: ship.Ship, aliens: Group, bullets: Bullet,
    2. play_button: Button):
    3. """更新屏幕上的图像,并切换到新屏幕"""
    4. # 每次循环重绘屏幕
    5. screen.fill(ai_settings.bg_color)
    6. ship.blitme()
    7. # 绘制外星人
    8. aliens.draw(screen)
    9. # 重绘子弹
    10. for bullet in bullets.sprites():
    11. bullet.draw_bullet()
    12. if not stats.game_active:
    13. play_button.draw_button()
    14. # 最近绘制的屏幕可见
    15. pygame.display.flip()

    主方法中创建按钮实例,并将其传入update_screen方法中

    1. # 创建play按钮
    2. play_button = Button(ai_settings, screen, "Play")

    19.开始游戏或重置游戏

  • 在game_functions.py中加入监视与按钮相关的鼠标事件
    1. def check_events(ai_settings, screen, ship, bullets, stats: GameStatus, play_button: Button):
    2. """响应按键和鼠标事件"""
    3. for event in pygame.event.get():
    4. # 用户按下键盘
    5. if event.type == pygame.KEYDOWN:
    6. check_keydown_events(event, ai_settings, screen, ship, bullets)
    7. elif event.type == pygame.KEYUP:
    8. check_keyup_events(event, ship)
    9. elif event.type == pygame.K_SPACE:
    10. fire_bullets(ai_settings, )
    11. elif event.type == pygame.MOUSEBUTTONDOWN:
    12. # 若按下按钮
    13. mouse_x, mouse_y = pygame.mouse.get_pos()
    14. check_play_button(stats, play_button, mouse_x, mouse_y)
    15. def check_play_button(stats: GameStatus, play_button: Button, mouse_x, mouse_y):
    16. """在玩家单击play时开始游戏"""
    17. if play_button.rect.collidepoint(mouse_x, mouse_y):
    18. stats.game_active = True

    其中mouse.get_pos返回一个元组,表示鼠标点击的坐标,我们用play_button.rect.collidepoint方法判断是否与按钮坐标重合

  • 接下来重置游戏,因为上面仅对第一次点击有用

  • 再次修改check_lpay_button方法

    1. def check_play_button(ai_settings, screen, stats: GameStatus, play_button: Button, mouse_x, mouse_y, aliens, ship,
    2. bullets):
    3. """在玩家单击play时开始游戏"""
    4. if play_button.rect.collidepoint(mouse_x, mouse_y):
    5. # 重置游戏并统计信息
    6. stats.reset_status()
    7. stats.game_active = True
    8. # 清空外星人和子弹的列表
    9. bullets.empty()
    10. aliens.empty()
    11. # 创建外星人,并让飞船居中
    12. create_fleet(ai_settings, screen, ship, aliens)
    13. ship.center_ship()

    我们新加了这个方法的参数,不要忘了在调用这个方法的位置加上(pycharm中ctrl+alt+h可以查看调用次方法的方法)

  • 现在还是有个问题,如果玩家在点击按钮后再次点击,会出现再次重置的情况,所以我们再加入对stats.game_active的判断,同时再让点击后光标不可见

    1. def check_play_button(ai_settings, screen, stats: GameStatus, play_button: Button, mouse_x, mouse_y, aliens, ship,
    2. bullets):
    3. """在玩家单击play时开始游戏"""
    4. button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    5. if button_clicked and not stats.game_active:
    6. #让光标不可见
    7. pygame.mouse.set_visible(False)
    8. # 重置游戏并统计信息
    9. stats.reset_status()
    10. stats.game_active = True
    11. # 清空外星人和子弹的列表
    12. bullets.empty()
    13. aliens.empty()
    14. # 创建外星人,并让飞船居中
    15. create_fleet(ai_settings, screen, ship, aliens)
    16. ship.center_ship()

    修改ship_hit方法,让游戏重置时,鼠标可见

    1. def ship_hit(ai_settings: Settings, status: GameStatus, screen, ship: ship.Ship, aliens, bullets):
    2. """响应外星人撞到飞船"""
    3. # 将飞船数量ship_left减一
    4. if status.ships_left > 0:
    5. status.ships_left -= 1
    6. # 清空外星人和子弹
    7. aliens.empty()
    8. bullets.empty()
    9. # 创建一群新的外星人,重置飞船
    10. create_fleet(ai_settings, screen, ship, aliens)
    11. ship.center_ship()
    12. # 暂停
    13. sleep(0.5)
    14. else:
    15. status.game_active = False
    16. pygame.mouse.set_visible(True)

    20.加快游戏节奏

  • 我们修改Settings.py中的属性来加快游戏
    1. class Settings():
    2. def __init__(self):
    3. """ 初始化游戏时的静态设置"""
    4. self.screen_width = 1200
    5. self.screen_height = 800
    6. self.bg_color = (230, 230, 230)
    7. # 飞船设置
    8. self.ship_speed_factor = 1.0
    9. self.ship_limit = 3
    10. # 子弹设置
    11. self.bullet_speed_factor = 0.7
    12. self.bullet_width = 3
    13. self.bullet_height = 15
    14. self.bullet_color = 60, 60, 60
    15. # 限制子弹数量
    16. self.bullets_allowed = 3
    17. # 外星人设置
    18. self.alien_speed_factor = 0.5 # 外星人水平移动速度
    19. self.fleet_drop_speed = 10 # 外星人竖直移动速度
    20. self.fleet_direction = 1 # 移动方向: 1为向右,-1向左
    21. # 以什么样的速度加快游戏节奏
    22. self.speedup_scale = 1.1
    23. self.initialize_dynamic_settings()
    24. def initialize_dynamic_settings(self):
    25. """初始化游戏进行而变化的设置"""
    26. self.ship_speed_factor = 1.5
    27. self.bullet_speed_factor = 3
    28. self.alien_speed_factor = 1
    29. self.fleet_direction = 1
    30. def increase_speed(self):
    31. """提高速度设置"""
    32. self.ship_speed_factor *= self.speedup_scale
    33. self.alien_speed_factor *= self.speedup_scale
    34. self.alien_speed_factor *= self.speedup_scale

    增加了一个倍率属性和两个方法

    1. def check_play_button(ai_settings: Settings, screen, stats: GameStatus, play_button: Button, mouse_x, mouse_y, aliens,
    2. ship,
    3. bullets):
    4. """在玩家单击play时开始游戏"""
    5. button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    6. if button_clicked and not stats.game_active:
    7. #重置游戏节奏
    8. ai_settings.initialize_dynamic_settings()
    9. 。。。。。。。。。。。。。。。。。。。。。。。

  • 接下来修改

game_functions.py中的check_bullet_alien_collision

  1. def check_bullet_alien_collision(ai_settings: Settings, screen, ship, aliens, bullets):
  2. # 检查是否有子弹击中外星人
  3. collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
  4. # 更新外星人
  5. if len(aliens) == 0:
  6. bullets.empty()
  7. #增加游戏节奏
  8. ai_settings.increase_speed()
  9. create_fleet(ai_settings, screen, ship, aliens)
  • 但是现在还有个问题,我们重置游戏时游戏节奏没有重置
    1. def check_play_button(ai_settings: Settings, screen, stats: GameStatus, play_button: Button, mouse_x, mouse_y, aliens,
    2. ship,
    3. bullets):
    4. """在玩家单击play时开始游戏"""
    5. button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    6. if button_clicked and not stats.game_active:
    7. #重置游戏节奏
    8. ai_settings.initialize_dynamic_settings()

    21.计分

  • 新增game_status.py中GameStatus类中的属性
    1. def reset_status(self):
    2. """初始化在游戏运行期间可能变化的信息"""
    3. self.ships_left = self.ai_settings.ship_limit
    4. self.score = 0

    新建scoreboard.py模块,并创建Scoreboard类:

    1. class Scoreboard():
    2. """显示得分信息的类"""
    3. def __init__(self, ai_settings: Settings, screen: Surface, status: GameStatus):
    4. """初始化得分涉及的属性"""
    5. self.screen = screen
    6. self.screen_rect = screen.get_rect()
    7. self.ai_settings = ai_settings
    8. self.status = status
    9. # 显示得分时的字体设置
    10. self.text_color = (30, 30, 30)
    11. self.font = pygame.font.SysFont(None, 48)
    12. # 准备初始得分图像
    13. self.prep_score()
    14. def prep_score(self):
    15. """将得分转换为渲染图像"""
    16. score_str = str(self.status.score)
    17. self.score_image = self.font.render(score_str, True, self.text_color)
    18. # 将得分显示在屏幕右上角
    19. self.score_rect = self.score_image.get_rect()
    20. self.score_rect.right = self.screen_rect.right - 20
    21. self.score_rect.top = 20
    22. def show_score(self):
    23. """在屏幕上显示得分"""
    24. self.screen.blit(self.score_image, self.score_rect)

    22.创建记分牌

  • 在主方法中循环前创建得分牌实例
    1. # 创建一个记分牌
    2. sb = Scoreboard(ai_settings, screen, stats)

    并将其传入循环中的update_screen方法中

  • game_functions.py

    1. def update_screen(ai_settings: Settings, screen, stats: GameStatus, ship: ship.Ship, aliens: Group, bullets: Bullet,
    2. play_button: Button, sb: Scoreboard):
    3. """更新屏幕上的图像,并切换到新屏幕"""
    4. 。。。。。。。。。。。。。。
    5. # 显示得分
    6. sb.show_score()
    7. # 最近绘制的屏幕可见
    8. pygame.display.flip()

    接下来我们开始增加分数

  • settings.py中加入分数设置

    1. def initialize_dynamic_settings(self):
    2. """初始化游戏进行而变化的设置"""
    3. self.ship_speed_factor = 1.5
    4. self.bullet_speed_factor = 0.7
    5. self.alien_speed_factor = 0.7
    6. self.fleet_direction = 1
    7. # 计分
    8. self.alien_points = 50
  •  game_functions.py中修改方法
    1. def check_bullet_alien_collision(ai_settings: Settings, screen, ship, aliens, bullets, stats: GameStatus,
    2. sb: Scoreboard):
    3. # 检查是否有子弹击中外星人
    4. collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
    5. #增加分数
    6. if collisions:
    7. for aliens in collisions.values():
    8. stats.score += ai_settings.alien_points * len(aliens)
    9. sb.prep_score()
    10. # 更新外星人
    11. if len(aliens) == 0:
    12. bullets.empty()
    13. # 增加游戏节奏
    14. ai_settings.increase_speed()
    15. create_fleet(ai_settings, screen, ship, aliens)

    其中collisions是一个字典,我们拿到他的值,这个值是一个列表,其中包括我们一颗子弹打掉的全部飞船(不排除一箭双雕),所以求出列表长度来算分

  • 不要忘了在形参中加入新的值并修改调用此方法传入的参数

  • 接下来我们设置游戏难度提高后的点数

  • settings.py

    1. class Settings():
    2. def __init__(self):
    3. 。。。。。。。。。。。。。。
    4. # 点数提高速度
    5. self.score_scale = 1.5
    6. def increase_speed(self):
    7. 。。。。。。。。。。。。。。
    8. """提高点数"""
    9. self.alien_points = int(self.alien_points * self.score_scale)

    为了让记分牌跟以前那种街机风格的记分牌一样,每三位用“,”隔开,我们修改prep_score方法

  • scoreboard.py

    1. def prep_score(self):
    2. """将得分转换为渲染图像"""
    3. # 将得分圆整
    4. rounded_score = int(round(self.status.score, -1))
    5. score_str = "{:,}".format(rounded_score)
    6. # score_str = str(self.status.score)删去
    7. self.score_image = self.font.render(score_str, True, self.text_color)
    8. # 将得分显示在屏幕右上角
    9. self.score_rect = self.score_image.get_rect()
    10. self.score_rect.right = self.screen_rect.right - 20
    11. self.score_rect.top = 20

    其中round()中的-1表示我们向10取整

  • 23.显示最高得分

  • scoreboard.py
    1. def __init__(self, ai_settings: Settings, screen: Surface, status: GameStatus):
    2. """初始化得分涉及的属性"""
    3. 。。。。。。。。。。。。
    4. self.prep_high_score()
    5. def show_score(self):
    6. """在屏幕上显示得分"""
    7. 。。。。。。。。。。。。。。。。。
    8. self.screen.blit(self.high_score_image, self.high_score_rect)
    9. def prep_high_score(self):
    10. """将最高得分转换为渲染的图像"""
    11. high_score = int(round(self.status.high_score, -1))
    12. high_score_str = "{:,}".format(high_score)
    13. self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.ai_settings.bg_color)
    14. # 将最高得分显示在屏幕中央
    15. self.high_score_rect = self.high_score_image.get_rect()
    16. self.high_score_rect.centerx = self.screen_rect.centerx
    17. self.high_score_rect.top = self.score_rect.top

    接下来我们判断是否诞生了最高分

  • game_functions.py加入

    1. def check_high_score(stats: GameStatus, sb: Scoreboard):
    2. """检查是否诞生了最高分"""
    3. if stats.high_score < stats.score:
    4. stats.high_score = stats.score
    5. sb.prep_high_score()

    我们需要在check_bullet_collision中调用分数判断

    1. def check_bullet_alien_collision(ai_settings: Settings, screen, ship, aliens, bullets, stats: GameStatus,
    2. sb: Scoreboard):
    3. # 检查是否有子弹击中外星人
    4. collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
    5. # 增加分数
    6. if collisions:
    7. for aliens in collisions.values():
    8. stats.score += ai_settings.alien_points * len(aliens)
    9. sb.prep_score()
    10. check_high_score(stats, sb)
    11. 。。。。。。。。。。。。。。。

    24、显示等级

  • 增加属性:
  • game_status.py
    1. def reset_status(self):
    2. """初始化在游戏运行期间可能变化的信息"""
    3. 。。。。。。。。。。。。。
    4. self.level = 1

    scoreboard.py

    1. def __init__(self, ai_settings: Settings, screen: Surface, status: GameStatus):
    2. """初始化得分涉及的属性"""
    3. 。。。。。。。。。。。。。。。。
    4. self.prep_level()
    5. def show_score(self):
    6. """在屏幕上显示得分"""
    7. 。。。。。。。。。。。。。。。。。。
    8. self.screen.blit(self.level_image, self.level_rect)
    9. def prep_level(self):
    10. """将等级渲染为图像"""
    11. self.level_image
    12. self.level_image = self.font.render(str(self.status.level), True, self.text_color,
    13. self.ai_settings.bg_color)
    14. """将等级放在得分下方"""
    15. self.level_rect = self.level_image.get_rect()
    16. self.level_rect.right = self.score_rect.right
    17. self.level_rect.top = self.score_rect.bottom + 10

    game_functions.py中修改

    1. def check_bullet_alien_collision(ai_settings: Settings, screen, ship, aliens, bullets, stats: GameStatus,sb: Scoreboard):
    2. 。。。。。。。。。。。。。。。。。。。。。。。。。
    3. # 更新外星人
    4. if len(aliens) == 0:
    5. bullets.empty()
    6. # 增加游戏节奏
    7. ai_settings.increase_speed()
    8. # 如果外星人都被消灭,就提高一个等级
    9. stats.level += 1
    10. sb.prep_level()
    11. create_fleet(ai_settings, screen, ship, aliens)

    为了每次点击play按钮时重置记分牌,我们修改

    1. def check_play_button(ai_settings: Settings, screen, stats: GameStatus, play_button: Button, mouse_x, mouse_y, aliens,
    2. ship, bullets, sb: Scoreboard, ):
    3. """在玩家单击play时开始游戏"""
    4. ...........................................
    5. # 重置得分牌图像
    6. sb.prep_score()
    7. sb.prep_high_score()
    8. sb.prep_level()
    9. # 清空外星人和子弹的列表
    10. bullets.empty()
    11. aliens.empty()
    12. # 创建外星人,并让飞船居中
    13. create_fleet(ai_settings, screen, ship, aliens)
    14. ship.center_ship()

    我们新传进来了个参数sb(ScoreBoard类)

  • 25.显示剩余飞船

  • ship.py
    1. class Ship(Sprite):
    2. def __init__(self, screen, ai_settings: Settings):
    3. """初始化飞船,并设置其起始位置"""
    4. super(Ship, self).__init__()
    5. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。

    让飞船继承sprite类,这样我们可以加入编组中管理

  • scoreboard.py类修改

    1. class Scoreboard():
    2. """显示得分信息的类"""
    3. def __init__(self, ai_settings: Settings, screen: Surface, status: GameStatus):
    4. """初始化得分涉及的属性"""
    5. 。。。。。。。。。。。。。。
    6. self.prep_ships()
    7. def show_score(self):
    8. """在屏幕上显示得分"""
    9. 。。。。。。。。。。。。。。。。。。
    10. self.ships.draw(self.screen)
    11. def prep_ships(self):
    12. """显示还剩下多少飞船"""
    13. self.ships = Group()
    14. for ship_number in range(self.status.ships_left):
    15. ship = Ship(self.screen, self.ai_settings)
    16. ship.rect.x = 10 + ship_number * ship.rect.width
    17. ship.rect.y = 10
    18. self.ships.add(ship)

    game_functions.py修改,调用prep_ships方法

    1. def check_play_button(ai_settings: Settings, screen, stats: GameStatus, play_button: Button, mouse_x, mouse_y, aliens,
    2. ship, bullets, sb: Scoreboard, ):
    3. """在玩家单击play时开始游戏"""
    4. 。。。。。。。。。。。。。。。。。。
    5. # 重置得分牌图像
    6. sb.prep_score()
    7. sb.prep_high_score()
    8. sb.prep_level()
    9. sb.prep_ships()
    10. # 清空外星人和子弹的列表
    11. bullets.empty()
    12. aliens.empty()
    13. # 创建外星人,并让飞船居中
    14. create_fleet(ai_settings, screen, ship, aliens)
    15. ship.center_ship()

    接下来我们在飞船撞到外星人时更新ships编组

    1. def ship_hit(ai_settings: Settings, status: GameStatus, screen, ship: ship.Ship, aliens, bullets, sb: Scoreboard):
    2. """响应外星人撞到飞船"""
    3. # 将飞船数量ship_left减一
    4. if status.ships_left > 0:
    5. status.ships_left -= 1
    6. # 更新记分牌
    7. sb.prep_ships()
    8. 。。。。。。。。。。。。。。。。。。

    我们又加了一个sb参数,按ctrl+alt+h查看调用此方法的函数,依次修改函数形参

  • 最终结果

完结撒花,本来没想到需要这么多字,打的我手疼(哭)。。。。没有辛劳也有苦劳,祝点赞的各位看官bug少少,头发多多~~~~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/121654?site
推荐阅读
相关标签
  

闽ICP备14008679号