今天,我将学习如何在游戏《外星人入侵》中添加外星人:
5.1 创建外星人:
首先,我们需要编写一个名为“Alien”的类:
这个类的大部分代码都与 Ship 类相似:
-
首先,需要导入模块
pygame。Alien 的方法__init__()接受三个参数:self,ai_settings和screen。 -
加载外星人图像后,使用
get_rect()获取相应的属性rect, -
我将外星人放在屏幕左上角附近。为此,可以将每个外星人的左边距都设置为外星人的宽度,并将上边距设置为外星人的高度(见19-20行)。
-
最后,我定义了方法
blitme(),它根据指定的位置将图像绘制到屏幕上。
下面还需要在alien_invasion.py中创建一个Alien 实例:
在这里,导入新创建的Alien 类(第4行处),并在进入主 while 循环前创建了一个Alien 实例(第17行)。没有修改外星人的位置,因此该 while 循环没有任何新东西,但我们在第25行修改了对update_screen() 的调用,传递了一个外星人实例。
5.2 在屏幕上显示外星人:
为让外星人出现在屏幕上,需要在update_screen() 中调用其方法blitme() :
在37-40行中,先绘制飞船和子弹,再绘制外星人,让外星人在屏幕上位于最前面:
5.3 创建一群外星人:
第一个外星人正确地现身后,下面需要来学习编写绘制一群外星人的代码,为创建一行外星人,首先在alien_invasion.py中创建一个名为aliens 的空编组,用于存储全部外星人,再调用game_functions.py中创建外星人群的函数:
这里需要特别注意一下:由于我们不再在alien_invasion.py中直接创建外星人,因此无需在这个文件中导入Alien 类。
可以看到,在第17行处创建了一个空编组,用于存储所有的外星人。接下来,需要调用稍后将编写的函数create_fleet()(见第20行),并将ai_settings 、对象screen 和空编组aliens 传递给它。然后,修改对update_screen() 的调用,让它能够访问外星人编组(见27行处)。
同时,还需要修改update_screen() :
对编组调用draw() 时,Pygame自动绘制编组的每个元素,绘制位置由元素的属性rect 决定。在这里,aliens.draw(screen) 在屏幕上绘制编组中的每个外星人。
现在可以创建外星人群了。下面是新函数create_fleet() ,将它放在game_functions.py的末尾。我们还需要导入Alien 类,因此要在文件game_functions.py开头添加相应 的import 语句:
-
为放置外星人,我们需要知道外星人的宽度和高度,因此在执行计算前,我们先创建一个外星人(见60行处)。
-
在第61行处,我们从外星人的
rect属性中获取外星人宽度,并将这个值存储到alien_width中,以免反复访问属性rect。 -
在第62行中,我们计算可用于放置外星人的水平空间,以及其中可容纳多少个外星人。
-
相比于前面介绍的工作,这里唯一的不同是使用了
int()来确保计算得到的外星人数量为整数(见第63行),因为我们不希望某个外星人只显示一部分,而且函数range()也需要一个整数。 -
接下来,我们编写了一个循环,它从零数到要创建的外星人数(见66行处)。在这个循环的主体中,我们创建一个新的外星人,并通过设置x坐标将其加入当前行(见第68行)。将每个外星人都往右推一个外星人的宽度。
-
接下来我们将外星人宽度乘以2,得到每个外星人占据的空间(其中包括其右边的空白区域),再据此计算当前外星人在当前行的位置。
-
最后,我们将每个新创建的外星人都添加到编组
aliens中。
如下图所示,如果现在运行这个游戏,将看到一行外星人:
5.4 创建不止一行的外星人:
要创建外星人群,需要计算屏幕可容纳多少行,并对创建一行外星人的循环重复相应的次数:
-
为计算屏幕可容纳多少行外星人,我们使用了函数
get_number_rows(),这个函数与get_number_aliens_x()类似。这里使用了int(),因为我们同样不想创建不完整的外星人行。 -
为创建多行,需要使用两个嵌套在一起的循环:一个外部循环和一个内部循环(见第78行)。其中的内部循环创建一行外星人,而外部循环从零数到要创建的外星人行数。Python将重复执行创建单行外星人的代码,重复次数为
number_rows。 -
为嵌套循环,编写一个新的 for 循环,在调用
create_alien()时,传递了一个表示行号的实参,将每行都沿屏幕依次向下放置。create_alien()的定义需要一个用于存储行号的形参。在create_alien()中,我们修改外星人的 y 坐标(见第64行处),并在第一行外星人上方留出与外星人等高的空白区域。相邻外星人行的y 坐标相差外星人高度的两倍,因此我们将外星人高度乘以2,再乘以行号。第一行的行号为0,因此第一行的垂直位置不变,而其他行都沿屏幕依次向下放置。
需要注意的是,在create_fleet() 的定义中,还新增了一个用于存储ship对象的形参,因此在alien_invasion.py中调用create_fleet() 时,需要传递实参ship :
如果你现在运行这个游戏,将看到一群外星人,如下图所示: