昨天我们已经实现了一群敌人的移动,如果你运行成功的话,会发现子弹会穿过敌人,因为我们没有检测碰撞。今天来实现射杀敌人的功能吧~
2.5 射杀敌人
要让子弹能够击落外星人,我 们将使用sprite.groupcollide() 检测两个编组的成员之间的碰撞。
2.5.1 检测子弹与敌人的碰撞
子弹击中敌人时,我们要马上知道,以便碰撞发生后让敌人立即消失。为此,我们将在更新子弹的位置后立即检测碰撞。方法sprite.groupcollide() 将每颗子弹的rect 同每个敌人的rect 进行比较,并返回一个字典,其中包含发生了碰撞的子弹和敌人。在这个字典中,每个键都是一颗子弹,而相应的值都是被击中的敌人(实现记分系统时,也会用到这个字典)。
在函数update_bullets() 中,使用下面的代码来检查碰撞:
def update_bullets(bullets):
# 更新子弹的位置
bullets.update() # 删除已消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
# 检查是否有子弹击中了敌人
# 如果是这样,就删除相应的子弹和敌人
collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
新增的这行代码遍历编组bullets 中的每颗子弹,再遍历编组aliens中的每个敌人。每当有子弹和敌人的rect 重叠时,groupcollide() 就在它返回的字典中添加一个键-值对。两个实参True 告诉Pygame删除发生碰撞的子弹和敌人。(要模拟能够穿行到屏幕顶端的高能子弹——消灭它击中的每个敌人,可将第一个布尔实参设置为False ,并让第二个布尔实参为True 。这样被击中的敌人将消失,但所有的子弹都始终有效,直到抵达屏幕顶端后消失。) 我们调用update_bullets() 时,传递了实参aliens :
while True:
gf.check_events(ai_settings,screen,ship,bullets)
ship.update()
gf.update_bullets(aliens,bullets)
gf.update_aliens(ai_settings,aliens)
gf.update_screen(ai_settings,screen,ship,aliens,bullets)
现在运行游戏,便可以射杀敌人了,然而敌人全部消失后,我们需要增加新的敌人,下面我们来实现更新新的敌人。
2.5.2 更新新的敌人
要在敌人群被消灭后又显示一群敌人,首先需要检查编组aliens 是否为空。如果为空,就调用create_fleet() 。我们将在update_bullets() 中执行这种检查,因为敌人都是在这里被消灭的:
def update_bullets(ai_settings,screen,ship,aliens,bullets):
# 更新子弹的位置
bullets.update() # 删除已消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
# 检查是否有子弹击中了敌人
# 如果是这样,就删除相应的子弹和敌人
collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
if len(aliens) == 0:
# 删除现有子弹并新建一群敌人
bullets.empty()
create_fleet(ai_settings,screen,ship,aliens)
记得更新主程序中的update_bullets函数:
while True:
gf.check_events(ai_settings,screen,ship,bullets)
ship.update()
gf.update_bullets(ai_settings,screen,ship,aliens,bullets)
gf.update_aliens(ai_settings,aliens)
gf.update_screen(ai_settings,screen,ship,aliens,bullets)
2.5.3 提高子弹的速度
我们发现子弹穿梭的速度有点缓慢,调整子弹速度值到正常水平:
#子弹设置
self.bullet_speed_factor = 3
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60,60,60
self.bullets_allowed = 3
这里我调成了3,不同电脑的速度值有差别,需要根据不同的电脑来设定。
2.5.4 重构update_bullets()
下面来重构update_bullets() ,使其不再完成那么多任务。我们将把处理子弹和敌人碰撞的代码移到一个独立的函数中:
def update_bullets(ai_settings,screen,ship,aliens,bullets):
# 更新子弹的位置
bullets.update() # 删除已消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
# 检查是否有子弹击中了敌人
# 如果是这样,就删除相应的子弹和敌人
check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets)
def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets):
collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
if len(aliens) == 0:
# 删除现有子弹并新建一群敌人
bullets.empty()
create_fleet(ai_settings,screen,ship,aliens)
OK,现在来测试一下吧。下一节我们要增加结束游戏的功能。越来越完整了,加油!