在今天的学习中,我将学习如何能够写出程序使得游戏结束:
8.1 检测外星人和飞船的碰撞:
我们首先检查外星人和飞船之间的碰撞,以便外星人撞上飞船时我们能够作出合适的响应。我们在更新每个外星人的位置后立即检测外星人和飞船之间的碰撞:
方法spritecollideany()
接受两个实参:一个精灵和一个编组。它检查编组是否有成员与精灵发生了碰撞,并在找到与精灵发生了碰撞的成员后就停止遍历编组。在这里, 它遍历编组aliens
,并返回它找到的第一个与飞船发生了碰撞的外星人。 如果没有发生碰撞,spritecollideany()
将返回 None ,因此第118行处的 if 代码块不会执行。如果找到了与飞船发生碰撞的外星人,它就返回这个外星人,因此 if 代码块将执行:打印“Ship hit!!!”(见第119行)。
现在,还需要将ship
传递给update_aliens()
:
现在如果运行这个游戏,如下图所示,每当有外星人撞到飞船时,终端窗口都将显示“ Ship hit !!! ”:
8.2 响应外星人和飞船的碰撞:
现在需要编写一个用于跟踪游戏统计信息的新类——GameStats
,并将其保存为文件game_stats.py:
在这个游戏运行期间,我们只创建一个GameStats
实例,但每当玩家开始新游戏时,需要重置一些统计信息。为此,我们在方法reset_stats()
中初始化大部分统计信息,而不是在__init__()
中直接初始化它们。我们在__init__()
中调用这个方法,这样创建GameStats
实例时将妥善地设置这些统计信息(见第7行处),同时在玩家开始新游戏时也能调用reset_stats()
。 当前只有一项统计信息——ships_left
,其值在游戏运行期间将不断变化。一开始玩家拥有的飞船数存储在settings.py的ship_limit
中:
我们还需对alien_invasion.py做些修改,以创建一个GameStats
实例:
可以看到,我们导入了新类GameStats
(见第7行处),创建了一个名为stats
的实例(见第17行处),再调用update_aliens()
并添加了实参stats
、screen
和ship
(见第30行处)。现在,有外星人撞到飞船时,我们就可以使用这些实参来跟踪玩家还有多少艘飞船,以及创建一群新的外星人。
我们想得到的功能是:有外星人撞到飞船时,我们将余下的飞船数减1,创建一群新的外星人,并将飞船重新放置到屏幕底端中央
下面将实现这些功能的大部分代码放到函数ship_hit()
中:
我们首先从模块time
中导入了函数sleep()
,以便使用它来让游戏暂停。新函数ship_hit()
在飞船被外星人撞到时作出响应。在这个函数内部,将余下的飞船数减1(见第115行),然后清空编组aliens
和bullets
(见118-119行)。接着我们建一群外星人,并将飞船居中(见122-123行),稍后将在Ship
类中添加方法center_ship()
。
最后,我们更新所有元素后(但在将修改显示到屏幕前)暂停, 让玩家知道其飞船被撞到了(见第126行)。屏幕将暂时停止变化,让玩家能够看到外星人撞到了飞船。函数sleep()
执行完毕后,将接着执行函数update_screen()
,将新的外星人群绘制到屏幕上。 我们还更新了update_aliens()
的定义,使其包含形参stats
、screen
和bullets
(见第128行),让它能够在调用ship_hit()
时传递这些值。
下面是新方法center_ship()
,请将其添加到ship.py的末尾:
为让飞船居中,我们将飞船的属性center
设置为屏幕中心的 x 坐标,而该坐标是通过属性screen_rect
获得的。
如下图所示,在一个外星人撞到飞船后,游戏暂停后,然后将出现一群新的外星人,而飞船将重置在屏幕底端居中:
8.3 响应外星人到达屏幕底端:
如果有外星人到达屏幕底端,我们将像有外星人撞到飞船那样作出响应:
函数check_aliens_bottom()
检查是否有外星人到达了屏幕底端。到达屏幕底端后,外星人的属性rect.bottom
的值大于或等于屏幕的属性rect.bottom
的值(见第132行)。如果有外星人到达屏幕底端,我们就调用ship_hit()
;只要检测到一个外星人到达屏幕底端,就无需检查其他外星人,因此我们在调用ship_hit()
后退出循环。
我们在更新所有外星人的位置并检测是否有外星人和飞船发生碰撞后调用check_aliens_bottom()
(见第146行)。
现在,每当有外星人撞到飞船或抵达屏幕底端时,都将出现一群新的外星人:
8.4 使游戏结束:
下面在GameStats
中添加一个作为标志的属性game_active
,以便在玩家的飞船用完后结束游戏:
现在在ship_hit()
中添加代码,在玩家的飞船都用完后将game_active
设置为 False :
ship_hit()
的大部分代码都没变。我们将原来的所有代码都移到了一个 if 语句块中,这条 if 语句检查玩家是否至少还有一艘飞船。如果是这样,就创建一群新的外星人,暂停一会儿,再接着往下执行。如果玩家没有飞船了,就将game_active
设置为 False 。
如下图所示,现在,运行这个游戏时,它将在飞船用完后停止不动: