4.1 添加射击功能:
为了添加射击功能。我们将编写玩家按空格键时发射子弹(小矩形)的代码。子弹将在屏幕中向上穿行,抵达屏幕上边缘后消失,首先,更新settings.py来添加子弹设置:
如11-14行所示,这些设置创建宽3像素、高15像素的深灰色子弹。子弹的速度比飞船稍低。
下面来创建存储 Bullet 类的文件bullet.py:
简要分析一下:
-
Bullet 类继承了我们从模块
pygame.sprite
中导入的Sprite
类。通过使用Sprite
,可将游戏中相关的元素编组,进而同时操作编组中的所有元素(第二行处)。 -
在12行处,我们创建了子弹的属性
rect
。子弹并非基于图像的,因此我们必须使用pygame.Rect()
类从空白开始创建一个矩形。创建这个类的实例时,必须提供矩形左上角的 x 坐标和 y 坐标,还有矩形的宽度和高度。我们在(0, 0)处创建这个矩形,但接下来的两行代码将其移到了正确的位置。 -
子弹应从飞船顶部射出,因此我们将表示子弹的
rect
的top
属性设置为飞船的rect
的top
属性,让子弹看起来像是从飞船中射出的(15行)。 -
在18行,我们将子弹的 y 坐标存储为小数值,以便能够微调子弹的速度。
-
在20-21行处,我们将子弹的颜色和速度设置分别存储到
self.color
和self.speed_factor
中。 -
方法
update()
管理子弹的位置。发射出去后,子弹在屏幕中向上移动,这意味着y坐标将不断减小,因此为更新子弹的位置,我们从self.y
中减去self.speed_factor
的值(见26行)。接下来,我们将self.rect.y
设置为self.y
的值(见27行)。属性speed_factor
让我们能够随着游戏的进行或根据需要提高子弹的速度,以调整游戏的行为。子弹发射后,其 x 坐标始终不变,因此子弹将沿直线垂直地往上穿行。 -
需要绘制子弹时,我们调用
draw_bullet()
。函数draw.rect()
使用存储在self.color
中的颜色填充表示子弹的rect
占据的屏幕部分。
4.2 将子弹存储到编组中:
我们导入了pygame.sprite
中的Group
类。在16行处,我们创建了一个Group
实例,并将其命名为bullets
。这个编组是在 while 循环外面创建的,这样就无需每次运行该循环时都创建一个新的子弹编组。
我们将bullets
传递给了check_events()
和update_screen()
。在check_events()
中,需要在玩家按空格键时处理bullets
;而在update_screen()
中,需要更新要绘制到屏幕上的bullets
。
当你对编组调用update()
时,编组将自动对其中的每个sprite调用update()
,因此代码行bullets.update()
将为编组bullets
中的每颗子弹调用bullet.update()
。
4.3 控制飞船发射子弹:
-
编组
bullets
传递给了check_keydown_events()
(见第6行)。玩家按空格键时,创建一颗新子弹(一个名为new_bullet 的Bullet
实例),并使用方法add()
将其加入到编组bullets
中(见13-14行);代码bullets.add(new_bullet)
将新子弹存储到编组bullets
中。 -
在
check_events()
的定义中,我们需要添加形参bullets
(见23行处);调用check_keydown_events()
时,我们也需要将bullets
作为实参传递给它。 -
在32行处,我们给在屏幕上绘制子弹的
update_screen()
添加了形参bullets
。方法bullets.sprites()
返回一个列表,其中包含编组bullets
中的所有精灵。为在屏幕上绘制发射的所有子弹,我们遍历编组bullets
中的精灵,并对每个精灵都调用draw_bullet()
(见35-36行)。
如图所示,如果此时运行alien_invasion.py,将能够左右移动飞船,并发射任意数量的子弹。子弹在屏幕上向上穿行,抵达屏幕顶部后消失:
4.4 删除已经消失的子弹:
在 for 循环中,不应从列表或编组中删除条目,因此必须遍历编组的副本。我们使用了方法copy()
来设置for 循环(25行处),这让我们能够在循环中修改bullets
。我们检查每颗子弹,看看它是否已从屏幕顶端消失(见第26行)。如果是这样,就将其从bullets
中删除(27行处)。在第28行,我们使用了一条 print 语句,以显示当前还有多少颗子弹, 从而核实已消失的子弹确实删除了。 如果这些代码没有问题,如下图所示,我们发射子弹后查看终端窗口时,将发现随着子弹一颗颗地在屏幕顶端消失,子弹数将逐渐降为零。运行这个游戏并确认子弹已被删除后,便可以将这条 print 语句删除:
4.5 限制子弹的数量:
首先,我们需要在settings.py中存储所允许的最大子弹数:
这将未消失的子弹数限制为3颗。在game_functions.py的check_keydown_events()
中,我们在创建新子弹前检查未消失的子弹数是否小于该设置:
玩家按空格键时,我们检查bullets
的长度。如果len(bullets)
小于3,我们就创建一个新子弹;但如果已有3颗未消失的子弹,则玩家按空格键时什么都不会发生。如下图所示,现在运行这个游戏,屏幕上最多只能有3颗子弹: