Python应用实例(一)外星人入侵(六)

1.让外星人群移动

下面来让外星人群在屏幕上向右移动,撞到屏幕边缘后下移一定的量,再沿相反的方向移动。我们将不断移动所有的外星人,直到外星人被全部消灭,或者有外星人撞上飞船或抵达屏幕底端。下面先让外星人向右移动。

1.1 向右移动外星人群

为移动外星人群,将使用alien.py中的方法update()。对于外星人群中的每个外星人,都要调用它。首先,添加一个控制外星人速度的设置:

settings.py

在这里插入代码片    def __init__(self):
        --snip--
        # 外星人设置
        self.alien_speed = 1.0

再使用这个设置来实现update():

alien.py

      def __init__(self, ai_game):
          """初始化外星人并设置其初始位置。"""
          super().__init__()
          self.screen = ai_game.screen
          self.settings = ai_game.settings
          --snip--

      def update(self):
          """向右移动外星人。"""
❶         self.x += self.settings.alien_speed
❷         self.rect.x = self.x

在__init__()中添加了属性settings,以便能够在update()中访问外星人的速度。每次更新外星人时,都将它向右移动,移动量为alien_speed的值。我们使用属性self.x跟踪每个外星人的准确位置,该属性可存储小数值(见❶)。然后,使用self.x的值来更新外星人的rect的位置(见❷)。

主while循环中已调用了更新飞船和子弹的方法,现在还需更调用更新每个外星人位置的方法:

alien_invasion.py

        while True:
            self._check_events()
            self.ship.update()
            self._update_bullets()
            self._update_aliens()
            self._update_screen()

需要编写一些代码来管理外星人群的移动,因此新建一个名为_update_aliens()的方法。我们在更新子弹后再更新外星人的位置,因为稍后要检查是否有子弹击中了外星人。

将这个方法放在模块的什么地方都无关紧要,但为确保代码组织有序,我将它放在方法_update_bullets()的后面,以便与while循环中的调用顺序一致。下面是_update_aliens()的第一版:

alien_invasion.py

    def _update_aliens(self):
        """更新外星人群中所有外星人的位置。"""
        self.aliens.update()

对编组调用方法update(),这将自动对每个外星人调用方法update()。如果现在运行这个游戏,你将看到外星人群向右移动,并在屏幕右边缘消失。

1.2 创建表示外星人移动方向的设置

下面来创建让外星人撞到屏幕右边缘后向下移动、再向左移动的设置。实现这种行为的代码如下:

settings.py

         # 外星人设置
         self.alien_speed = 1.0
         self.fleet_drop_speed = 10
         # fleet_direction为1表示向右移,为-1表示向左移。
         self.fleet_direction = 1

设置fleet_drop_speed指定有外星人撞到屏幕边缘时,外星人群向下移动的速度。将这个速度与水平速度分开是有好处的,便于分别调整这两个速度。

要实现设置fleet_direction,可将其设置为文本值,如’left’或’right’,但这样就必须编写if-elif语句来检查外星人群的移动方向。鉴于只有两个可能的方向,我们使用值1和-1来表示,并在外星人群改变方向时在这两个值之间切换。(向右移时需要增大每个外星人的[插图]坐标,而向左移时需要减小每个外星人的[插图]坐标,因此使用数字来表示方向十分合理。)

1.3 检查外星人是否撞到了屏幕边缘

现在需要编写一个方法来检查外星人是否撞到了屏幕边缘,还需修改update()让每个外星人都沿正确的方向移动。这些代码位于Alien类中:

alien.py

      def check_edges(self):
          """如果外星人位于屏幕边缘,就返回True。"""
          screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right or self.rect.left <= 0:
                return True

      def update(self):
          """向左或向右移动外星人。"""
❷         self.x += (self.settings.alien_speed *
                          self.settings.fleet_direction)
          self.rect.x = self.x

可对任意外星人调用新方法check_edges(),看其是否位于屏幕左边缘或右边缘。如果外星人的rect的属性right大于或等于屏幕的rect的right属性,就说明外星人位于屏幕右边缘;如果外星人的rect的left属性小于或等于0,就说明外星人位于屏幕左边缘(见❶)。

我们修改方法update(),将移动量设置为外星人速度和fleet_direction的乘积,让外星人向左或向右移动(见❷)。如果fleet_direction为1,就将外星人的当前[插图]坐标增大alien_speed,从而将外星人向右移;如果fleet_direction为-1,就将外星人的当前[插图]坐标减去alien_speed,从而将外星人向左移。

1.4 向下移动外星人群并改变移动方向

有外星人到达屏幕边缘时,需要将整群外行星下移,并改变它们的移动方向。为此,需要在AlienInvasion中添加一些代码,因为要在这里检查是否有外星人到达了左边缘或右边缘。我们编写方法_check_fleet_edges()和_change_fleet_direction(),并且修改_update_aliens()。这些新方法将放在_create_alien()后面,但其实放在AlienInvasion类中的什么位置都无关紧要:

alien_invasion.py

      def _check_fleet_edges(self):
          """有外星人到达边缘时采取相应的措施。"""for alien in self.aliens.sprites():
              if alien.check_edges():
❷                 self._change_fleet_direction()
                  break

      def _change_fleet_direction(self):
          """将整群外星人下移,并改变它们的方向。"""
          for alien in self.aliens.sprites():
❸             alien.rect.y += self.settings.fleet_drop_speed
          self.settings.fleet_direction *= -1

在_check_fleet_edges()中,遍历外星人群并对其中的每个外星人调用check_edges()(见❶)。如果check_edges()返回True,就表明相应的外星人位于屏幕边缘,需要改变外星人群的方向,因此调用_change_fleet_direction()并退出循环(见❷)。在_change_fleet_direction()中,遍历所有外星人,将每个外星人下移设置fleet_drop_speed的值(见❸)。然后,将fleet_direction的值改为其当前值与-1的乘积。调整外星人群移动方向的代码行没有包含在for循环中,因为我们要调整每个外星人的垂直位置,但只想调整外星人群移动方向一次。

下面显示了对_update_aliens()所做的修改:

alien_invasion.py

    def _update_aliens(self):
        """
        检查是否有外星人位于屏幕边缘,
        并更新整群外星人的位置。
        """
        self._check_fleet_edges()
        self.aliens.update()

我们将方法_update_aliens()修改成了先调用_check_fleet_edges(),再更新每个外星人的位置。

如果现在运行这个游戏,外星人群将在屏幕上来回移动,并在抵达屏幕边缘后向下移动。现在可以开始射杀外星人,并检查是否有外星人撞到飞船或抵达了屏幕底端。

posted @ 2023-07-08 14:18  小幽余生不加糖  阅读(14)  评论(0编辑  收藏  举报  来源