项目需求:
在游戏《外星人入侵》中,玩家控制着一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头键左右移动飞船,还可使用空格键进行射击。游戏开始时,一群外星人出现在天空中,他们在屏幕中向下移动。玩家的任务是射杀这些外星人。玩家将所有外星人都消灭干净后,将出现一群新的外星人,他们移动的速度。只要有外星人撞到了玩家的飞船或到达了屏幕底部,玩家就损失一艘飞船。玩家损失三艘飞船后,游戏结束。
在第一阶段中,我们创建了一艘可以左右移动的飞船,这艘飞船在用户按空格键时能够开火。设置好这种行为后,我们就能够将注意力转向外星人,并提高这款游戏的可玩性。
往期博客
关于:设置飞船的博客
关于:给飞船添加射击功能的博客
在上一章节中,我们又添加了外星人群,并设置了子弹撞击到外星人的处理。
关于:设置外星人群的博客
本章内容如下:
结束游戏
当玩家未在约定时间内消灭入侵的外星人,或外星人抵达屏幕边缘,在或外星人撞击飞船,击毁飞船的所有生命值,那么游戏结束,玩家只能通过重新开始游戏来进行新的游戏。
检测外星人和飞船碰撞
首先检查外星人和飞船的碰撞,以便外星人撞击飞船后作出响应。
在更新每个外星人的位置后立即检测外星人和飞船之间的碰撞。扫描二维码关注公众号,回复: 15605847 查看本文章
game_functions.py:
def update_aliens(ai_settings,ship,aliens):
#检查是否有外星人位于屏幕边缘,并更新整群外星人的位置
check_fleet_edges(ai_settings,aliens)
#更新外新人群中所有外星人的位置
aliens.update()
if pygame.sprite.spritecollideany(ship,aliens):
print("Ship hit!!!")
方法 spritecollideany:
该方法接受两个参数,一个精灵和一个编组。
它检查编组是否有成员与精灵发生碰撞,并在找到与精灵发生碰撞的成员后停止遍历编组。如果没有发生碰撞,返回 None。但如果有外星人与飞船发生碰撞就返回编组内的精灵,也就是外星人。
当外星人和飞船发生碰撞时,需要执行的任务有很多:
需要删除余下的所有外星人和子弹,让飞船重新居中,以及创建一群外星人。编写完成这些任务的代码前,需要确定检测外星人和飞船的碰撞方法是否可行。而为确定这一点,最简单的方式是编写一条print语句。
响应外星人和飞船碰撞
在这里,我们需要确定外星人与飞船发生碰撞时该做些什么。
不需销毁 ship,并重新创建飞船,
而是通过跟踪游戏的统计信息来记录飞船被撞了多少次(跟踪统计信息有助于记分)。
统计游戏信息的 GameStats类:
game_stats.py:
class GameStats():
#跟踪游戏的统计信息
def __init__(self,ai_settings):
self.ai_settings = ai_settings
self.rest_stats()
def rest_stats(self):
#初始化在游戏运行期间可能变化的统计信息
self.ships_left = self.ai_settings.ship_limit
在 GameStats类中,我们定义了跟踪游戏的统计信息,init方法中,并没有直接初始化信息,而是调用了下方定义的 rest_stats 用来初始化信息的方法。
ships_left 变量存储的值是:
settings.py:
#飞船的生命值
self.ship_limit = 3
既然有了 用于跟踪游戏信息的统计类,我们还需更改一下 alien_invasion.py,
因为我们要在这个主文件中导入新创建的类。
alien_invasion.py:
from game_stats import GameStats
def run_game():
#创建一个用于存储游戏统计信息的实例
stats = GameStats(ai_settings)
# while 循环来控制游戏
while True:
gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets)
我们导入了新类: GameStats,其目的在于,创建其实例,在玩家控制的飞船被外星人撞击时,使用 update_aliens()
传递的参数来跟踪玩家还有多少艘飞船,以及创建一群新的外星人。
现在,当外星人撞击到飞船后,我们将余下的飞船数量减1,创建一群新的外星人,并将飞船重新放置到屏幕底端中央。哦对!别忘了让游戏暂停一段时间,因为要让玩家在新外星人群出现前注意发生了碰撞。
game_functions:
from time import sleep
def ship_hit(ai_settings,stats,screen,ship,aliens,bullets):
#响应外星人撞到的飞船
stats.ships_left -= 1
#清空外星人列表和子弹列表
aliens.empty()
bullets.empty()
#创建一群新的外星人,并将飞船放到屏幕底部中央
create_fleet(ai_settings,screen,ship,aliens)
ship.center_ship()
#暂停
sleep(0.5)
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):
#检查是否有外星人位于屏幕边缘,并更新整群外星人的位置
check_fleet_edges(ai_settings,aliens)
#更新外新人群中所有外星人的位置
aliens.update()
if pygame.sprite.spritecollideany(ship,aliens):
#print("Ship hit!!!")
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
在 time模块中导入函数 sleep() 用于暂停游戏。
新函数 ship_hit 在飞船被外星人撞击时,作出响应。在整个的函数内部,将余下的飞船数量减1,然后清空编组外星人和子弹。在将飞船和外星人进行处理,并将游戏暂停。
ship.py:
def center_ship(self):
self.center = self.screen_rect.centerx
为让被撞击后的飞船回到屏幕中央,定义了 center_ship方法。将飞船的属性 center设置为屏幕中心的x坐标,而该坐标是通过属性screen_rect获得的。
有外星人到达屏幕底端
如果有外星人抵达屏幕底部,我们将像有外星人撞到飞船那样作出响应。
添加一个执行这项任务的函数,并将其命名为 check_aliens_bottom():
game_functions.py
def check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets):
#检查是否有外星人到达底部
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= ship.rect.bottom:
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
break
检查是否有外星人到达屏幕的底部,如果到达,调用 ship_hit 方法将飞船放到屏幕中央。检测的条件是通过 对比 飞船和外星人的 bottom值,如果外星人的值大于飞船的值,说明外星人到达底部。
在更新所有外星人的位置和检测是否外星人和飞船发生碰撞后调用上述定义的新方法:
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):
check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bulltets)
游戏结束
下面我们定义一个标志,以便在玩家的飞船生命值消耗为空后结束游戏:
game_stats.py:
#将该标志定义在 init 方法当中
#在游戏刚启动时处于活动状态
self.game_active = True
玩家控制的飞船生命数值为0时,我们设置为 False。
game_functions.py:
def ship_hit(ai_settings,stats,screen,ship,aliens,bullets):
if stats.ships_left > 0:
#响应外星人撞到的飞船
stats.ships_left = -1
#清空外星人列表和子弹列表
aliens.empty()
bullets.empty()
#创建一群新的外星人,并将飞船放到屏幕底部中央
create_fleet(ai_settings,screen,ship,aliens)
ship.center_ship()
#暂停
sleep(0.5)
else:
stats.game_active = False
确定应运行游戏的哪些部分
# while 循环来控制游戏
while True:
gf.check_events(ai_settings,screen,ship,bullets)
if stats.game_active:
ship.update()
gf.update_bullets(ai_settings,screen,ship,aliens,bullets)
gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets)
bullets.update()
gf.update_screen(ai_settings,screen,ship,aliens,bullets)