天天看點

python-飛機大戰5.敵機出場-項目實戰

目标

  • 使用 定時器 添加敵機
  • 設計 ​

    ​Enemy​

    ​ 類

01. 使用定時器添加敵機

運作 備課代碼,觀察 敵機的 出現規律:

  1. 遊戲啟動後,每隔 1 秒 會 出現一架敵機
  2. 每架敵機 向螢幕下方飛行,飛行 速度各不相同
  3. 每架敵機出現的 水準位置 也不盡相同
  4. 當敵機 從螢幕下方飛出,不會再飛回到螢幕中

1.1 定時器

  • 在 ​

    ​pygame​

    ​ 中可以使用 ​

    ​pygame.time.set_timer()​

    ​ 來添加 定時器
  • 所謂 定時器,就是 每隔一段時間,去 執行一些動作
set_timer(eventid, milliseconds) -> None      
  • ​set_timer​

    ​ 可以建立一個 事件
  • 可以在 遊戲循環 的 事件監聽 方法中捕獲到該事件
  • 第 1 個參數 事件代号 需要基于常量 ​

    ​pygame.USEREVENT​

    ​ 來指定
  • ​USEREVENT​

    ​ 是一個整數,再增加的事件可以使用 ​

    ​USEREVENT + 1​

    ​ 指定,依次類推...
  • 第 2 個參數是 事件觸發 間隔的 毫秒值

定時器事件的監聽

  • 通過 ​

    ​pygame.event.get()​

    ​ 可以擷取目前時刻所有的 事件清單
  • 周遊清單 并且判斷 ​

    ​event.type​

    ​ 是否等于 ​

    ​eventid​

    ​,如果相等,表示 定時器事件 發生

1.2 定義并監聽建立敵機的定時器事件

​pygame​

​ 的 定時器 使用套路非常固定:

  1. 定義 定時器常量 —— ​

    ​eventid​

  2. 在 初始化方法 中,調用 ​

    ​set_timer​

    ​ 方法 設定定時器事件
  3. 在 遊戲循環 中,監聽定時器事件
1) 定義事件
  • 在 ​

    ​plane_sprites.py​

    ​ 的頂部定義 事件常量
# 敵機的定時器事件常量
CREATE_ENEMY_EVENT = pygame.USEREVENT      
  • 在 ​

    ​PlaneGame​

    ​ 的 初始化方法 中 建立使用者事件
# 4. 設定定時器事件 - 每秒建立一架敵機
pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)      
2) 監聽定時器事件
  • 在 ​

    ​__event_handler​

    ​ 方法中增加以下代碼:
def __event_handler(self):
    
    for event in pygame.event.get():
    
        # 判斷是否退出遊戲
        if event.type == pygame.QUIT:
            PlaneGame.__game_over()
        elif event.type == CREATE_ENEMY_EVENT:
            print("敵機出場...")      

02. 設計 ​

​Enemy​

​ 類

  1. 遊戲啟動後,每隔 1 秒 會 出現一架敵機
  2. 每架敵機 向螢幕下方飛行,飛行 速度各不相同
  3. 每架敵機出現的 水準位置 也不盡相同
  4. 當敵機 從螢幕下方飛出,不會再飛回到螢幕中
  • 初始化方法
  • 指定 敵機圖檔
  • 随機 敵機的 初始位置 和 初始速度
  • 重寫 update() 方法
  • 判斷 是否飛出螢幕,如果是,從 精靈組 删除

2.1 敵機類的準備

  • 在 ​

    ​plane_sprites​

    ​ 建立 ​

    ​Enemy​

    ​ 繼承自 ​

    ​GameSprite​

  • 重寫 初始化方法,直接指定 圖檔名稱
  • 暫時 不實作 随機速度 和 随機位置 的指定
  • 重寫 ​

    ​update​

    ​ 方法,判斷是否飛出螢幕
class Enemy(GameSprite):
    """敵機精靈"""
    
    def __init__(self):
        
        # 1. 調用父類方法,建立敵機精靈,并且指定敵機的圖像
        super().__init__("./images/enemy1.png")

        # 2. 設定敵機的随機初始速度

        # 3. 設定敵機的随機初始位置
    
    def update(self):
        
        # 1. 調用父類方法,讓敵機在垂直方向運動
        super().update()
        
        # 2. 判斷是否飛出螢幕,如果是,需要将敵機從精靈組删除
        if self.rect.y >= SCREEN_RECT.height:
            print("敵機飛出螢幕...")      

2.2 建立敵機

  1. 在 ​

    ​__create_sprites​

    ​,添加 敵機精靈組
  • 敵機是 定時被建立的,是以在初始化方法中,不需要建立敵機
  1. 在 ​

    ​__event_handler​

    ​,建立敵機,并且 添加到精靈組
  • 調用 精靈組 的 ​

    ​add​

    ​ 方法可以 向精靈組添加精靈
  1. 在 ​

    ​__update_sprites​

    ​,讓 敵機精靈組 調用 ​

    ​update​

    ​ 和 ​

    ​draw​

    ​ 方法
  • 修改 ​

    ​plane_main​

    ​ 的 ​

    ​__create_sprites​

    ​ 方法
# 敵機組
self.enemy_group = pygame.sprite.Group()      
  • 修改 ​

    ​plane_main​

    ​ 的 ​

    ​__update_sprites​

    ​ 方法
self.enemy_group.update()
self.enemy_group.draw(self.screen)      
  • 定時出現敵機
elif event.type == CREATE_ENEMY_EVENT:
    self.enemy_group.add(Enemy())      

2.3 随機敵機位置和速度

1) 導入子產品
  • 在導入子產品時,建議 按照以下順序導入
1. 官方标準子產品導入
2. 第三方子產品導入
3. 應用程式子產品導入      
  • 修改 ​

    ​plane_sprites.py​

    ​ 增加 ​

    ​random​

    ​ 的導入
import random      
2) 随機位置
  • ​bottom = y + height​

  • ​y = bottom - height​

3) 代碼實作
  • 修改 初始化方法,随機敵機出現 速度 和 位置
def __init__(self):

    # 1. 調用父類方法,建立敵機精靈,并且指定敵機的圖像
    super().__init__("./images/enemy1.png")

    # 2. 設定敵機的随機初始速度 1 ~ 3
    self.speed = random.randint(1, 3)

    # 3. 設定敵機的随機初始位置
    self.rect.bottom = 0
    
    max_x = SCREEN_RECT.width - self.rect.width
    self.rect.x = random.randint(0, max_x)      

2.4 移出螢幕銷毀敵機

  • 敵機移出螢幕之後,如果 沒有撞到英雄,敵機的曆史使命已經終結
  • 需要從 敵機組 删除,否則會造成 記憶體浪費
檢測敵機被銷毀
  • ​__del__​

    ​ 内置方法會在對象被銷毀前調用,在開發中,可以用于 判斷對象是否被銷毀
def __del__(self):
    print("敵機挂了 %s" % self.rect)      
代碼實作
  • 判斷敵機是否飛出螢幕,如果是,調用 ​

    ​kill()​

    ​ 方法從所有組中删除
def update(self):
    super().update()
    
    # 判斷敵機是否移出螢幕
    if self.rect.y >= SCREEN_RECT.height:
        # 将精靈從所有組中删除
        self.kill()      

繼續閱讀