Python 外星人入侵游戏(二):外星人(下)

文章目录

  • 6 结束游戏
    • 6.1 检测外星人和飞船碰撞
    • 6.2 响应外星人和飞船碰撞
    • 6.3 有外星人到达屏幕底端
    • 6.4 游戏结束
  • 7 确定应运行游戏的哪些部分

来源:《Python编程:从入门到实践》

6 结束游戏

  • 如果玩家没能在足够短的时间内将整群外星人都消灭干净,且有外星人撞到了飞船,飞船将被摧毁
  • 与此同时,还限制飞船数,有外星人抵达屏幕底端时,飞船也将被摧毁
  • 玩家用光飞船,Game Over…

6.1 检测外星人和飞船碰撞

  • 在更新每个外星人的位置后立即检测外星人和飞船之间的碰撞

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()接受两个实参:一个精灵和一个编组
  • 它检测编组是否有成员与精灵发生了碰撞,并在找到与精灵发生了碰撞的成员后就停止遍历编组
  • 如果没有发生碰撞,spritecollideany()返回None,因此if代码块不会执行

alien_invasion.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!!!")      
  • 如果现在运行游戏,每当有外星人撞到飞船时,终端窗口将显示"Ship hit!!!"

6.2 响应外星人和飞船碰撞

  • 现在需要确定外星人与飞船碰撞时,该做些什么
  • 不销毁ship实例并创建一个新的ship实例,而是跟踪游戏的统计信息来记录飞船被撞了多少次(跟踪统计信息还有助于记分)

game_stats.py

class GameStats():
    """跟踪游戏的统计信息"""
    def __init__(self, ai_settings):
        """初始化统计信息"""
        self.ai_settings = ai_settings
        self.reset_stats()
        
    def reset_stats(self):
        """初始化在游戏运行期间可能变化的统计信息"""
        self.ships_left = self.ai_settings.ship_limit
  • 当前只有一项信息——ships_left,它在游戏运行期间将不断变化
  • 一开始玩家拥有的飞船数存储在settings.py的ship_limit中

settings.py

        # 飞船的设置
        self.ship_speed_factor = 1.5
        self.ship_limit = 3
  • 下面对alien_invasion.py进行修改,创建一个GameStats实例

alien_invasion.py

--snip--
from game_stats import GameStats
from ship import Ship
--snip--

def run_game():
    --snip--
    pygame.display.set_caption("Alien Invasion")
    
    # 创建一个用于存储游戏统计信息的实例
    stats = GameStats(ai_settings)
    --snip--
    # 开始游戏的主循环
    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, stats, screen, ship, aliens, bullets)
        --snip--
  • 调用update_aliens()并添加了实参stats、screen和bullets。在有外星人撞到飞船时,将使用这些实参来跟踪玩家还有多少艘飞船,以及创建一群新的外星人
  • 有外星人撞到飞船时,我们将余下的飞船数-1,创建一群新的外星人,并将飞船重新放置到屏幕底端中央(还将让游戏暂停一段时间,让玩家在新外星人群出现前注意到发生了碰撞,并将重新创建外星人群)

game_functions.py

import sys
from time import sleep
--snip--

def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):
    """响应被外星人撞到的飞船"""
    # 将ship_left减去1
    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):
    --snip--
    # 检测外星人和飞船之间的碰撞
    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
  • 首先从模块time导入函数sleep(),以便使用它来暂停游戏
  • 新函数ship_hit()在飞船外星人相撞时做出响应
  • 稍后在Ship类中添加方法center_ship()
  • 最后更新所有原色后,暂停,让玩家知道飞船被撞到了
  • 函数sleep()执行完毕后,将接着执行函数update_screen(),将新的外星人群绘制到屏幕
  • 下面是新方法center_ship(),将其添加到ship.py的末尾:

ship.py

    def center_ship(self):
        """让飞船在屏幕上居中"""
        self.center = self.screen_rect.centerx

注意:我们根本没有创建多艘飞船,在整个游戏运行期间,都只创建了一个飞船实例,并在该飞船被撞到时将其居中

  • 运行这个游戏,射杀几个外星人,并让一个外星人撞到飞船。游戏暂停后,将出现一群新的外星人,而飞船将在屏幕底端居中

6.3 有外星人到达屏幕底端

  • 如果有外星人到达屏幕底端,将像有外星人撞到飞船那样做出响应
  • 添加一个执行这项任务的新函数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 >= screen_rect.bottom:
            # 像飞船被撞到一样进行处理
            ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
            break

def update_aliens(ai_settings, stats, screen, ship, aliens, bullets):
    --snip--
    # 检查是否有外星人到达屏幕底端
    check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets)  
  • 如果有外星人到达屏幕底端,就调用ship_hit()
  • 只要检查一个外星人到达底端,就无需检查其他外星人,因此在调用ship_hit()后退出循环

6.4 游戏结束

  • 现在的问题是这个游戏永远都不会结束,只是ships_left不断变成更小的负数

game_stats.py

def __init__(self, ai_settings):
        --snip--
        # 游戏刚启动时处于活动状态
        self.game_active = True
  • 现在在ship_hit()中添加代码,在玩家的飞船用完后将game_active设置为False

game_functions.py

def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):
    """响应被外星人撞到的飞船"""
    if stats.ships_left > 0:
        # 将ship_left减去1
        stats.ships_left -= 1
        --snip--
        # 暂停一会儿
        sleep(0.5)
        
    else:
        stats.game_active = False

7 确定应运行游戏的哪些部分

  • 在alien_invasion.py中,需要确定游戏的哪些部分在任何情况下都应运行,哪些部分仅在游戏处于活动状态时才运行:

alien_invasion.py

    # 开始游戏的主循环
    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)
            
        gf.update_screen(ai_settings, screen, ship, aliens, bullets)
  • 现在,运行游戏时,将在飞船用完后停止不动

Python 外星人入侵游戏(二):外星人(下)_第1张图片

  • Python 外星人入侵游戏(三):记分(上)

你可能感兴趣的:(Python学习)