1. 程式人生 > >Python13_專案一 :外星人入侵遊戲04(重構check_event() 以及 使飛船發射子彈)

Python13_專案一 :外星人入侵遊戲04(重構check_event() 以及 使飛船發射子彈)

為了使程式碼模組化、結構化,我們將check_event()函式中的按鍵響應,重構為兩個函式:分別是check_keydown() 【響應按鍵】和 check_keyup()  【響應鬆開】。

重構後的程式碼如下:(此程式碼為本節部分程式碼,整體程式碼稍後,這段程式碼看看就好

# 響應按鍵 03
def check_keydown(event, ai_settings, screen, ship, bullets):
    if event.key == pygame.K_RIGHT:
        # 向右移動飛船
        ship.moving_right = True
        # ship.rect.centerx += 10
    elif event.key == pygame.K_LEFT:
        # 向左移動飛船
        # ship.rect.centerx -= 10
        ship.moving_left = True


# 響應鬆開 03
def check_keyup(event, ship):
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False


# 響應按鍵和滑鼠事件
def check_event(ai_setting, screen, ship, bullets):  # 03

    for i in pygame.event.get():
        if i.type == pygame.QUIT:
            sys.exit()

        elif i.type == pygame.KEYDOWN:
            check_keydown(i, ai_setting, screen, ship, bullets) # 重構
        # 03   if i.key == pygame.K_RIGHT:
        # 03        # 向右移動飛船
        # 03        ship.moving_right = True
        # 03        # ship.rect.centerx += 10
        # 03    elif i.key == pygame.K_LEFT:
        # 03        # 向左移動飛船
        # 03        # ship.rect.centerx -= 10
        # 03        ship.moving_left = True

        elif i.type == pygame.KEYUP:
            check_keyup(i, ship)  # 重構
            # 03 if i.key == pygame.K_RIGHT:
            # 03    ship.moving_right = False
            # 03 elif i.key == pygame.K_LEFT:
            # 03    ship.moving_left = False

那麼接下來,就是要增加子彈。對於增加子彈,我們需要先在settings.py檔案中增加子彈的屬性。然後,寫一個bullet.py檔案,儲存Bullet類,為的是建立一個子彈的rect物件,並且能讓子彈從螢幕中繪製出來。具體檔案如下所示:

bullet.py程式碼如下所示:

import pygame
from pygame.sprite import Sprite        # 匯入精靈

# 一個對飛船發射的子彈進行管理的類
class Bullet(Sprite):
    def __init__(self,ai_setting,screen,ship):
        # 在飛船所處的位置建立一個子彈物件
        super().__init__()    # 初始化父類 2.7寫法super(Bullet,self).__init__()
        self.screen = screen

        # 在(0,0)處建立一個表示子彈的矩形,再設定正確的位置
        # 我們建立了子彈的屬性rect 。子彈並非基於影象的,因此我們必須使用pygame.Rect()類從空白開始建立一個矩形
        # 我們在(0, 0)處建立這個矩形,但接下來的兩行程式碼將其移到了正確的位置
        self.rect = pygame.Rect(0,0,ai_setting.bullet_width,ai_setting.bullet_height)
        # 我們將子彈的centerx設定為飛船的rect.centerx 。
        # 子彈應從飛船頂部射出,因此我們將表示子彈的rect的top屬性設定為飛船的rect的top屬性,
        # 讓子彈看起來像是從飛船中射出的
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top

        # 儲存用小數表示的子彈位置
        self.y = float(self.rect.y)

        self.color = ai_setting.bullet_color
        self.speed = ai_setting.bullet_speed_factor

    # 向上移動子彈
    def update(self, *args):
        # 更新表示子彈位置的小數值
        self.y -= self.speed
        # 更新表示子彈位置的rect的位置
        self.rect.y = self.y

    # 在螢幕上繪製子彈
    def draw_bullet(self):
        # 函式draw.rect()使用儲存在self.color中的顏色填充表示子彈的rect佔據的螢幕部分
        pygame.draw.rect(self.screen,self.color,self.rect)

然後附上更新後的其他.py檔案程式碼。

帶 03 標記的都是更新有關的!!!

settings.py

class Setting():            # 儲存《外星人入侵》中所有的設定類
    def __init__(self):     # 初始化遊戲設定
        self.screen_width = 1200        # 螢幕設定
        self.screen_height = 800
        self.bg_color = (230,230,230)

        self.ship_speed_factor = 1.5    # 02 設定飛船速度

        # 03 設定子彈
        self.bullet_speed_factor = 1    # 子彈速度
        self.bullet_width = 3           # 子彈寬度
        self.bullet_height = 15         # 子彈長度
        self.bullet_color = 60,60,60    # 子彈顏色
        self.bullet_allowed = 3         # 限制子彈數量為3

game_funtion.py

import sys
import pygame
from alien.bullet import Bullet  # 03


# 響應按鍵 03
def check_keydown(event, ai_settings, screen, ship, bullets):
    if event.key == pygame.K_RIGHT:
        # 向右移動飛船
        ship.moving_right = True
        # ship.rect.centerx += 10
    elif event.key == pygame.K_LEFT:
        # 向左移動飛船
        # ship.rect.centerx -= 10
        ship.moving_left = True
    # 03 建立一顆子彈,並將其加入到編組bullets中
    elif event.key == pygame.K_SPACE:
        if len(bullets) < ai_settings.bullet_allowed:   # 限制三個子彈
            # 玩家按空格鍵時,建立一顆新子彈(一個名為new_bullet 的Bullet 例項),
            new_bullet = Bullet(ai_settings, screen, ship)
            # 並使用方法add() 將其加入到編組bullets中
            bullets.add(new_bullet)


# 響應鬆開 03
def check_keyup(event, ship):
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False


# 響應按鍵和滑鼠事件
def check_event(ai_setting, screen, ship, bullets):  # 03

    for i in pygame.event.get():
        if i.type == pygame.QUIT:
            sys.exit()

        elif i.type == pygame.KEYDOWN:
            check_keydown(i, ai_setting, screen, ship, bullets) # 重構
        # 03   if i.key == pygame.K_RIGHT:
        # 03        # 向右移動飛船
        # 03        ship.moving_right = True
        # 03        # ship.rect.centerx += 10
        # 03    elif i.key == pygame.K_LEFT:
        # 03        # 向左移動飛船
        # 03        # ship.rect.centerx -= 10
        # 03        ship.moving_left = True

        elif i.type == pygame.KEYUP:
            check_keyup(i, ship)  # 重構
            # 03 if i.key == pygame.K_RIGHT:
            # 03    ship.moving_right = False
            # 03 elif i.key == pygame.K_LEFT:
            # 03    ship.moving_left = False

def update_screen(ai_setting, screen, ship, bullets):  # 更新螢幕上的影象,並切換到新螢幕
    # 每次迴圈時都重繪螢幕
    screen.fill(ai_setting.bg_color)
    # 03 在飛船和外星人後面重繪所有子彈
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    # 讓最近繪製的螢幕可見
    pygame.display.flip()

# 03 更新子彈位置,並刪除已經消失的子彈
def update_bullet(bullets):
    bullets.update()        # 更新子彈位置

    # 03 刪除已經消失,看不到的子彈
    for bull in bullets.copy():
        if bull.rect.bottom <= 0:
            bullets.remove(bull)
    print(len(bullets))

alien_invasion.py

# 02 import sys
import pygame
from alien.settings import Setting      # 01
from alien.ship import Ship             # 01
import alien.game_function as gf        # 02
from pygame.sprite import Group         # 03 pygame.sprite.Group 類類似於列表,但提供了有助於開發遊戲的額外功能


def run_game():          # 初始化遊戲,並且建立一個螢幕物件
    pygame.init()        # 初始化背景設定,讓Pygame能夠正確地工作
    # 01 screen = pygame.display.set_mode((1200, 800))     # 建立一個名為screen 的顯示視窗,括號裡是元組!!!
    # 01                                                   # 這個遊戲的所有圖形元素都將在其中繪製
    ai_set = Setting()                                     # 因為匯入類而做了程式碼替換
    screen = pygame.display.set_mode(
        (ai_set.screen_width,ai_set.screen_height)
    )
    # 01 bg_color = (230,230,230)         # 設定背景顏色

    pygame.display.set_caption('外星人入侵')
    # 建立一艘飛船物件
    ship = Ship(ai_set,screen)
    # 03 匯入Group類並且建立一個Group例項,用於儲存子彈的編組
    bullets = Group()

    # 為讓程式響應事件,我們編寫一個事件迴圈,以偵聽事件,並根據發生的事件執行相應的任務。
    while True:  # 遊戲的主迴圈
        # 02 for event in pygame.event.get():    # 監視鍵盤和滑鼠
        # 02     if event.type == pygame.QUIT:   #編寫一系列的if 語句來檢測並響應特定的事件
        # 02         sys.exit()                  # 我們呼叫sys.exit() 來退出遊戲
        gf.check_event(ai_set,screen,ship,bullets)    # 02 03
        ship.update()           # 02

        gf.update_bullet(bullets)      # 03
        # 03 bullets.update()   # 03
        # # 03 刪除已經消失,看不到的子彈
        # for bull in bullets.copy():
        #     if bull.rect.bottom <= 0:
        #         bullets.remove(bull)
        # print(len(bullets))

        # 01screen.fill(bg_color)                # 每次迴圈都重繪螢幕
        # 02 screen.fill(ai_set.bg_color)
        # 02 ship.blitme()                       # 呼叫blitme函式,使飛船出現
        # 02 pygame.display.flip()               # 讓最近繪製的螢幕可見

        gf.update_screen(ai_set,screen,ship,bullets)     # 02 03

run_game()