6.1 使外星人向右移动:

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

python 外星人 爆炸效果 python外星人游戏_ide

接着,需要使用这个设置来实现update()

python 外星人 爆炸效果 python外星人游戏_ide_02

每次更新外星人位置时,都将它向右移动,移动量为alien_speed_factor 的值。我们使用属性self.x 跟踪每个外星人的准确位置。然后,使用self.x 的值来更新外星人的rect 的位置(见28行处)。

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

python 外星人 爆炸效果 python外星人游戏_python 外星人 爆炸效果_03

最后,在文件game_functions.py末尾添加新函数update_aliens()

python 外星人 爆炸效果 python外星人游戏_python 外星人 爆炸效果_04

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

python 外星人 爆炸效果 python外星人游戏_ide_05


6.2 创建表示外星人移动方向的设置并检查外星人是否撞到了屏幕边缘:

下面来创建让外星人撞到屏幕右边缘后向下移动、再向左移动的设置:

python 外星人 爆炸效果 python外星人游戏_python_06

在17-18行中,设置fleet_drop_speed 指定了有外星人撞到屏幕边缘时,外星人群向下移动的速度。将这个速度与水平速度分开是有好处的,这样就可以分别调整这两种速度了。鉴于只有两个可能的方向,我们使用值 1 和 -1 来表示它们,并在外星人群改变方向时在这两个值之间切换。另外,鉴于向右移动时需要增大每个外星人的 x 坐标,而向左移动时需要减小每个外星人的 x 坐标,使用数字来表示方向更合理。

现在需要编写一个方法来检查是否有外星人撞到了屏幕边缘,还需修改update() ,以让每个外星人都沿正确的方向移动:

python 外星人 爆炸效果 python外星人游戏_pygame_07

我们可对任何外星人调用新方法check_edges() ,看看它是否位于屏幕左边缘右边缘。如果外星人的rectright 属性大于或等于屏幕的rectright 属性,就说明外星人位于屏幕右边缘(见第28行处)。如果外星人的rectleft 属性小于或等于0,就说明外星人位于屏幕左边缘(见第30行处)。

令笔者觉得巧妙的是: 通过修改方法update() ,将移动量设置为外星人速度fleet_direction 的乘积,让外星人向或向移。如果fleet_direction1,就将外星人当前的 x 坐标增大alien_speed_factor ,从而将外星人向右移;如果fleet_direction-1 ,就将外星人当前的 x 坐标减去alien_speed_factor ,从而将外星人向左移。


6.3 向下移动外星人群并改变其移动方向:

有外星人到达屏幕边缘时,需要将整群外星人下移,并改变它们的移动方向。我们需要对game_functions.py做修改,因为我们要在这里检查是否有外星人到达了左边缘或右边缘。为此,我们编写函数check_fleet_edges()change_fleet_direction() ,并对update_aliens() 进行修改:

python 外星人 爆炸效果 python外星人游戏_ide_08

  1. check_fleet_edges() 中,我们遍历外星人群,并对其中的每个外星人调用check_edges() (见第91行)。如果check_edges() 返回 True ,我们就知道相应的外星人位于屏幕边缘,需要改变外星人群的方向,因此我们调用change_fleet_direction() 并退出循环。
  2. change_fleet_direction() 中,我们遍历所有外星人,将每个外星人下移fleet_drop_speed 设置的值(见第98行);然后,将fleet_direction 的值修改为其当前值与 -1 的乘积。
  3. 我们修改了函数update_aliens() ,在其中通过调用check_fleet_edges() 来确定是否有外星人位于屏幕边缘。

现在,函数update_aliens() 包含形参ai_settings ,因此我们调用它时指定了与ai_settings 对应的实参:

python 外星人 爆炸效果 python外星人游戏_pygame_09

如下图所示,如果现在运行这个游戏,外星人群将在屏幕上来回移动,并在抵达屏幕边缘后向下移动:

python 外星人 爆炸效果 python外星人游戏_pygame_10


7.1 发射子弹射击外星人:

我们创建了飞船和外星人群,但子弹击中外星人时,将穿过外星人,因为我们还没有检查碰撞。在游戏编程中,碰撞指的是游戏元素重叠在一起。要让子弹能够击落外星人,我们将使用sprite.groupcollide() 检测两个编组的成员之间的碰撞。

子弹击中外星人时,我们要马上知道,以便碰撞发生后让外星人立即消失。为此,我们将在更新子弹的位置后立即检测碰撞。 方法sprite.groupcollide() 将每颗子弹的rect 同每个外星人的rect 进行比较,并返回一个字典,其中包含发生了碰撞的子弹和外星人。在这个字典中,每个都是一颗子弹,而相应的都是被击中的外星人。

在函数update_bullets() 中,使用下面的代码来检查碰撞:

python 外星人 爆炸效果 python外星人游戏_python_11

新增的这行代码遍历编组bullets 中的每颗子弹(第53行处),再遍历编组aliens 中的每个外星人。每当有子弹和外星人的rect 重叠时,groupcollide() 就在它返回的字典中添加一个键-值对。值得注意的是,两个实参 True 告诉Pygame删除发生碰撞的子弹和外星人。

我们调用update_bullets() 时,传递了实参aliens

python 外星人 爆炸效果 python外星人游戏_ide_12

如果此时运行这个游戏,被击中的外星人将消失。如图所示,其中有一部分外星人被击落:

python 外星人 爆炸效果 python外星人游戏_ide_13


7.2 生成新的外星人群:

要在外星人群被消灭后又显示一群外星人,首先需要检查编组aliens 是否为空。如果为空,就调用create_fleet() 。我们将在update_bullets() 中执行这种检查,因为外星人都是在这里被消灭的:

python 外星人 爆炸效果 python外星人游戏_pygame_14

在第55行处,我们检查编组aliens 是否为空。如果是,就使用方法empty() 删除编组中余下的所有精灵,从而删除现有的所有子弹。我们还调用了create_fleet() ,再次在屏幕上显示一群外星人。 现在,update_bullets() 的定义包含额外的形参ai_settingsscreenship ,因此我们需要更新alien_invasion.py中对update_bullets() 的调用:

python 外星人 爆炸效果 python外星人游戏_python_15

现在,如下图所示,当外星人群被消灭干净后,将立刻出现一个新的外星人群:

python 外星人 爆炸效果 python外星人游戏_ide_16