• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

《Python编程从入门到实践》第13章外星人来了

武飞扬头像
笨小古
帮助1

在这个项目中,要实现在屏幕左上角添加一个外星人,然后根据这个外星人的边距和屏幕尺寸来计算屏幕上可容纳多少个外星人,据此创建一系列外星人,使其填满尺寸屏幕上半部分;

之后要实现让外星人向两边和下方移动直到被外星人全部击落、有外星人撞到飞船或者有外星人抵达屏幕底端,在将全部外星人击落、有外星人撞到飞船或者有外星人抵达屏幕底端后,屏幕上将再出现一群外星人;

为了避免无休止地重复游戏而乏味无趣,可限制玩家可用的飞船数量,当飞船数量用完之后,游戏结束。

下面展示代码:

1.alien_invasion.py

  1.  
    import sys
  2.  
    import pygame
  3.  
    from time import sleep
  4.  
     
  5.  
    from settings import Settings
  6.  
    from ship import Ship
  7.  
    from bullet import Bullet
  8.  
    from alien import Alien
  9.  
    from game_stats import GameStats
  10.  
     
  11.  
     
  12.  
    class AlienInvasion:
  13.  
    """ 管理游戏资源和行为的类 """
  14.  
     
  15.  
    def __init__(self):
  16.  
    """ 初始化游戏并创建游戏资源 """
  17.  
    pygame.init()
  18.  
    self.settings = Settings()
  19.  
     
  20.  
    self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
  21.  
    self.settings.screen_width = self.screen.get_rect().width
  22.  
    self.settings.screen_height = self.screen.get_rect().height
  23.  
    pygame.display.set_caption("Alien Invasion")
  24.  
     
  25.  
    # 创建一个用于存储游戏统计信息的实例
  26.  
    self.stats = GameStats(self)
  27.  
     
  28.  
    self.ship = Ship(self)
  29.  
     
  30.  
    self.bullets = pygame.sprite.Group()
  31.  
    self.aliens = pygame.sprite.Group()
  32.  
     
  33.  
    self._create_fleet()
  34.  
     
  35.  
    def run_game(self):
  36.  
    """ 开始游戏的主循环 """
  37.  
    while True:
  38.  
    self._check_events()
  39.  
     
  40.  
    if self.stats.game_active:
  41.  
    self.ship.update()
  42.  
    self._update_bullets()
  43.  
    self._update_aliens()
  44.  
     
  45.  
    self._update_screen()
  46.  
     
  47.  
    def _update_bullets(self):
  48.  
    """ 更新子弹的位置并删除消失的子弹 """
  49.  
    # 更新子弹的位置
  50.  
    self.bullets.update()
  51.  
    # 删除消失的子弹
  52.  
    for bullet in self.bullets.copy():
  53.  
    if bullet.rect.bottom <= 0:
  54.  
    # ######## 此处有改动
  55.  
    # if bullet.rect.right >= self.ship.screen_rect.right:
  56.  
    self.bullets.remove(bullet)
  57.  
     
  58.  
    self._check_bullet_alien_collisions()
  59.  
     
  60.  
    def _check_bullet_alien_collisions(self):
  61.  
    """ 响应子弹和外星人碰撞 """
  62.  
    # 删除发生碰撞的子弹和外星人
  63.  
    pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)
  64.  
    '''
  65.  
    函数sprite.groupcollide()将一个编组中每个元素的rect同另一个编组中每个元素的rect及进行比较。
  66.  
    '''
  67.  
    if not self.aliens:
  68.  
    # 删除现有的所有子弹并新建一群外星人
  69.  
    self.bullets.empty()
  70.  
    self._create_fleet()
  71.  
     
  72.  
    def _update_aliens(self):
  73.  
    """
  74.  
    检查是否有外星人位于屏幕边缘,并更新外星人群中所有外星人的位置
  75.  
    """
  76.  
    self._check_fleet_edges()
  77.  
    self.aliens.update()
  78.  
     
  79.  
    # 检测外星人和飞船之间的碰撞
  80.  
    if pygame.sprite.spritecollideany(self.ship, self.aliens):
  81.  
    print("Ship hit!!!")
  82.  
    self._ship_hit()
  83.  
     
  84.  
    # 检查是否有外星人到达了屏幕底端
  85.  
    self._check_aliens_bottom()
  86.  
     
  87.  
    def _ship_hit(self):
  88.  
    """ 响应飞船被外星人撞到 """
  89.  
    if self.stats.ships_left > 0:
  90.  
    # 将ships_left减1
  91.  
    self.stats.ships_left -= 1
  92.  
     
  93.  
    # 清空余下的外星人和子弹
  94.  
    self.aliens.empty()
  95.  
    self.bullets.empty()
  96.  
     
  97.  
    # 创建一群新的外星人,并将飞船放到屏幕底端的中央
  98.  
    self._create_fleet()
  99.  
    self.ship.center_ship()
  100.  
     
  101.  
    # 暂停
  102.  
    sleep(0.5)
  103.  
    else:
  104.  
    self.stats.game_active = False
  105.  
     
  106.  
    def _check_events(self):
  107.  
    """ 响应按键和鼠标事件 """
  108.  
    for event in pygame.event.get():
  109.  
    if event.type == pygame.QUIT:
  110.  
    sys.exit()
  111.  
    elif event.type == pygame.KEYDOWN: # 按下键
  112.  
    self._check_keydown_events(event)
  113.  
    elif event.type == pygame.KEYUP: # 松开键
  114.  
    self._check_keyup_events(event)
  115.  
     
  116.  
    def _check_keydown_events(self, event):
  117.  
    """ 响应按键 """
  118.  
    if event.key == pygame.K_RIGHT: # 按下的键是右箭头键
  119.  
    # 向右移动飞船
  120.  
    self.ship.moving_right = True
  121.  
    elif event.key == pygame.K_LEFT: # 按下的键是左箭头键
  122.  
    # 向左移动飞船
  123.  
    self.ship.moving_left = True
  124.  
    elif event.key == pygame.K_UP:
  125.  
    # 向上移动飞船
  126.  
    self.ship.moving_up = True
  127.  
    elif event.key == pygame.K_DOWN:
  128.  
    # 向下移动飞船
  129.  
    self.ship.moving_down = True
  130.  
    elif event.key == pygame.K_q:
  131.  
    sys.exit()
  132.  
    elif event.key == pygame.K_SPACE:
  133.  
    self._fire_bullet()
  134.  
     
  135.  
    def _check_keyup_events(self, event):
  136.  
    """ 响应松开 """
  137.  
    if event.key == pygame.K_RIGHT: # 松开的键是右箭头键
  138.  
    self.ship.moving_right = False
  139.  
    elif event.key == pygame.K_LEFT: # 松开的键是左箭头键
  140.  
    self.ship.moving_left = False
  141.  
    elif event.key == pygame.K_UP: # 松开的键是上箭头键
  142.  
    self.ship.moving_up = False
  143.  
    elif event.key == pygame.K_DOWN: # 松开的键是下箭头键
  144.  
    self.ship.moving_down = False
  145.  
     
  146.  
    def _fire_bullet(self):
  147.  
    """ 创建一颗子弹,并将其加入编组bullets中 """
  148.  
    if len(self.bullets) < self.settings.bullets_allowed:
  149.  
    new_bullet = Bullet(self)
  150.  
    self.bullets.add(new_bullet)
  151.  
     
  152.  
    def _create_fleet(self):
  153.  
    """ 创建外星人群 """
  154.  
    # 创建一个外星人并计算一行可容纳多少个外星人
  155.  
    # 外星人的间距为外星人宽度
  156.  
    alien = Alien(self)
  157.  
    alien_width, alien_height = alien.rect.size
  158.  
    availiable_space_x = self.settings.screen_width - (2 * alien_width)
  159.  
    number_aliens_x = availiable_space_x // (2 * alien_width) 1
  160.  
     
  161.  
    # 计算屏幕可容纳多少行外星人
  162.  
    ship_height = self.ship.rect.height
  163.  
    availiable_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height)
  164.  
    number_rows = availiable_space_y // (2 * alien_height)
  165.  
     
  166.  
    # 创建外星人群
  167.  
    for row_number in range(number_rows):
  168.  
    for alien_number in range(number_aliens_x):
  169.  
    self._create_alien(alien_number, row_number)
  170.  
     
  171.  
    def _create_alien(self, alien_number, row_number):
  172.  
    """ 创建一个外星人并将其加入到当前行 """
  173.  
    alien = Alien(self)
  174.  
    alien_width, alien_height = alien.rect.size
  175.  
    alien.x = alien_width 2 * alien_width * alien_number
  176.  
    alien.rect.x = alien.x
  177.  
    # 这里很重要!!!
  178.  
    # 如果写作:
  179.  
    # alien.rect.x = alien_width 2 * alien_width * alien_number
  180.  
    # 屏幕只会出现一列外星人
  181.  
    # 原因是(alien_width 2 * alien_width * alien_number)
  182.  
    # 是计算当前外星人在当前行的位置,然后使用外星人的属性x来设置其rect的位置,这是创建外星人行列的过程,并不能展示外星人移动过程
  183.  
    # alien是类Alien()的实例,在Alien()中alien.x在一直变化,利用函数_update_aliens()更新,以此来展示外星人左右移动
  184.  
     
  185.  
    alien.rect.y = alien.rect.height 2 * alien.rect.height * row_number
  186.  
    self.aliens.add(alien)
  187.  
     
  188.  
    def _check_fleet_edges(self):
  189.  
    """ 外星人到达边缘时采取相应的措施 """
  190.  
    for alien in self.aliens.sprites():
  191.  
    if alien.check_edges():
  192.  
    self._change_fleet_firection()
  193.  
    break
  194.  
     
  195.  
    def _check_aliens_bottom(self):
  196.  
    """ 检查是否有外星人到达了屏幕底端 """
  197.  
    screen_rect = self.screen.get_rect()
  198.  
    for alien in self.aliens.sprites():
  199.  
    if alien.rect.bottom >= screen_rect.bottom:
  200.  
    # 像飞船被撞到一样处理
  201.  
    self._ship_hit()
  202.  
    break
  203.  
     
  204.  
    def _change_fleet_firection(self):
  205.  
    """ 将整群外星人下移,并改变它们方向 """
  206.  
    for alien in self.aliens.sprites():
  207.  
    alien.rect.y = self.settings.fleet_drop_speed
  208.  
    self.settings.fleet_direction *= -1
  209.  
     
  210.  
    def _update_screen(self):
  211.  
    """ 更新屏幕上的图像,并切换到新屏幕 """
  212.  
    self.screen.fill(self.settings.bg_color)
  213.  
    self.ship.blitme()
  214.  
    for bullet in self.bullets.sprites():
  215.  
    bullet.draw_bullet()
  216.  
     
  217.  
    self.aliens.draw(self.screen)
  218.  
     
  219.  
    pygame.display.flip()
  220.  
     
  221.  
     
  222.  
    if __name__ == '__main__':
  223.  
    # 创建游戏实例并运行游戏
  224.  
    ai = AlienInvasion()
  225.  
    ai.run_game()
学新通

2.settings.py

  1.  
    class Settings:
  2.  
    """ 存储游戏《外星人入侵》中所有设置的类 """
  3.  
     
  4.  
    def __init__(self):
  5.  
    """ 初始化游戏的设置 """
  6.  
    # 屏幕设置
  7.  
    self.screen_width = 1500
  8.  
    self.screen_height = 800
  9.  
    self.bg_color = (227, 227, 227)
  10.  
     
  11.  
    # 飞船设置
  12.  
    self.ship_speed = 1.5 # 速度:每次循环将移动1.5像素
  13.  
    self.ship_limit = 3 # 飞船数量限制
  14.  
     
  15.  
    # 子弹设置
  16.  
    self.bullet_speed = 3.0
  17.  
    self.bullet_width = 3
  18.  
    self.bullet_height = 15
  19.  
    self.bullet_color = (60, 60, 60) # 子弹颜色
  20.  
    self.bullets_allowed = 10 # 允许在屏幕中的子弹数量
  21.  
     
  22.  
    # 外星人设置
  23.  
    self.alien_speed = 1.0
  24.  
    self.fleet_drop_speed = 10
  25.  
    # fleet_direction为1表示右移,为-1表示左移
  26.  
    self.fleet_direction = 1
学新通

3.alien.py

  1.  
    import pygame
  2.  
    from pygame.sprite import Sprite
  3.  
     
  4.  
     
  5.  
    class Alien(Sprite):
  6.  
    """ 表示单个外星人的类 """
  7.  
     
  8.  
    def __init__(self, ai_game):
  9.  
    """ 初始化外星人并设置其起始位置 """
  10.  
    super().__init__()
  11.  
    self.screen = ai_game.screen
  12.  
    self.settings = ai_game.settings
  13.  
     
  14.  
    # 加载外星人图像并设置其rect属性
  15.  
    self.image = pygame.image.load('images/alien.bmp')
  16.  
    self.rect = self.image.get_rect()
  17.  
     
  18.  
    # 每个外星人最初都在屏幕左上角附近
  19.  
    self.rect.x = self.rect.width
  20.  
    self.rect.y = self.rect.height
  21.  
     
  22.  
    # 存储外星人的精确水平位置
  23.  
    self.x = float(self.rect.x)
  24.  
     
  25.  
    def check_edges(self):
  26.  
    """ 如果外星人位于屏幕边缘,就返回True """
  27.  
    screen_rect = self.screen.get_rect()
  28.  
    if self.rect.right >= screen_rect.right or self.rect.left <= 0:
  29.  
    return True
  30.  
     
  31.  
    def update(self):
  32.  
    """ 向左或向右移动外星人 """
  33.  
    self.x = (self.settings.alien_speed * self.settings.fleet_direction)
  34.  
    self.rect.x = self.x
学新通

4.ship.py

  1.  
    import pygame
  2.  
     
  3.  
     
  4.  
    class Ship:
  5.  
    """ 管理飞船的类 """
  6.  
     
  7.  
    def __init__(self, ai_game):
  8.  
    """ 初始化飞船并设置其初始位置 """
  9.  
    self.screen = ai_game.screen
  10.  
    self.settings = ai_game.settings
  11.  
    self.screen_rect = ai_game.screen.get_rect()
  12.  
     
  13.  
    # 加载飞船图像并获取其外接矩形
  14.  
    self.image = pygame.image.load('images/ship.bmp')
  15.  
    self.rect = self.image.get_rect()
  16.  
     
  17.  
    # 对于每艘新飞船,都将其放在屏幕底部的中央
  18.  
    self.rect.midbottom = self.screen_rect.midbottom
  19.  
     
  20.  
    # # 使飞船出现在屏幕中央而不是屏幕底部的中央
  21.  
    # self.rect.center = self.screen_rect.center
  22.  
     
  23.  
    # # 使飞船出现在屏幕左侧
  24.  
    # self.rect.midleft = self.screen_rect.midleft
  25.  
     
  26.  
    # 在飞船的属性x中储存小数值
  27.  
    self.x = float(self.rect.x)
  28.  
    self.y = float(self.rect.y)
  29.  
     
  30.  
    # 移动标志
  31.  
    self.moving_right = False
  32.  
    self.moving_left = False
  33.  
    self.moving_up = False
  34.  
    self.moving_down = False
  35.  
     
  36.  
    def update(self):
  37.  
    """ 根据移动标志调整飞船的位置 """
  38.  
    # 更新飞船而不是rect对象的x值
  39.  
    if self.moving_right and self.rect.right < self.screen_rect.right:
  40.  
    self.x = self.settings.ship_speed
  41.  
    if self.moving_left and self.rect.left > 0:
  42.  
    self.x -= self.settings.ship_speed
  43.  
     
  44.  
    # 更新飞船而不是rect对象的y值
  45.  
    if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
  46.  
    self.y = self.settings.ship_speed
  47.  
    if self.moving_up and self.rect.top > 0:
  48.  
    self.y -= self.settings.ship_speed
  49.  
     
  50.  
    # 根据self.x更新rect对象
  51.  
    self.rect.x = self.x
  52.  
    # 根据self.y更新rect对象
  53.  
    self.rect.y = self.y
  54.  
     
  55.  
    def center_ship(self):
  56.  
    """ 让飞船在屏幕低端居中 """
  57.  
    self.rect.midbottom = self.screen_rect.midbottom
  58.  
    self.x = float(self.rect.x)
  59.  
     
  60.  
    def blitme(self):
  61.  
    """ 在指定位置绘制飞船 """
  62.  
    self.screen.blit(self.image, self.rect)
学新通

5.bullet.py

  1.  
    import pygame
  2.  
    from pygame.sprite import Sprite
  3.  
     
  4.  
     
  5.  
    class Bullet(Sprite):
  6.  
    """ 管理飞船所发射子弹的类 """
  7.  
     
  8.  
    def __init__(self, ai_game):
  9.  
    """ 在飞船当前位置创建一个子弹位置 """
  10.  
    super().__init__()
  11.  
    self.screen = ai_game.screen
  12.  
    self.settings = ai_game.settings
  13.  
    self.color = self.settings.bullet_color
  14.  
     
  15.  
    # 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
  16.  
    self.rect = pygame.Rect(0, 0, self.settings.bullet_width, self.settings.bullet_height)
  17.  
    self.rect.midtop = ai_game.ship.rect.midtop
  18.  
     
  19.  
    # 储存用小数表示的子弹位置
  20.  
    self.y = float(self.rect.y)
  21.  
    # self.x = float(self.rect.x)
  22.  
     
  23.  
    def update(self):
  24.  
    """ 向上移动子弹 """
  25.  
    # 更新表示子弹位置的小数值
  26.  
    self.y -= self.settings.bullet_speed
  27.  
    # 更新表示子弹的rect的位置
  28.  
    self.rect.y = self.y
  29.  
     
  30.  
    # def update(self):
  31.  
    # """ 向右移动子弹 """
  32.  
    # # 更新表示子弹位置的小数值
  33.  
    # self.x = self.settings.bullet_speed
  34.  
    # # 更新表示子弹的rect的位置
  35.  
    # self.rect.x = self.x
  36.  
     
  37.  
    def draw_bullet(self):
  38.  
    """ 在屏幕上绘制子弹 """
  39.  
    pygame.draw.rect(self.screen, self.color, self.rect)
学新通

6.game_stats.py

  1.  
    class GameStats:
  2.  
    """ 跟踪游戏的统计信息 """
  3.  
     
  4.  
    def __init__(self, ai_game):
  5.  
    """ 初始化统计信息 """
  6.  
    self.settings = ai_game.settings
  7.  
    self.reset_stats()
  8.  
     
  9.  
    # 游戏刚启动时处于活动状态
  10.  
    self.game_active = True
  11.  
     
  12.  
    def reset_stats(self):
  13.  
    """ 初始化在游戏运行期间可能变化的统计信息 """
  14.  
    self.ships_left = self.settings.ship_limit

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhihaeeh
系列文章
更多 icon
同类精品
更多 icon
继续加载