嗨,各位程式碼冒險家!歡迎來到我的「順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作」第二十四天。在過去近兩週的時間裡,我們深度打造了《奇幻卡牌競技場》的核心邏輯,從 Player
類別到 GameManager
,再到複雜的 AI 策略。然而,一個遊戲光有內涵是不夠的,它還需要一個引人入勝的「舞台」。
今天,我們將正式踏入遊戲的視覺化領域,探討如何利用強大的 Pygame 函式庫 來建立遊戲視窗、載入字體,並繪製精美的背景,為我們的奇幻世界點亮第一道光芒。這一切都將在我們的專案主入口 main.py
檔案中實現。
任何 Pygame 應用程式的第一步,都是初始化其內部模組。這就像在演出開始前,確認所有燈光、音響設備都已準備就緒。
main.py
)import pygame
import sys
import os
def resource_path(relative_path):
"""取得資源的絕對路徑,不論是在開發環境還是打包後的 .exe。"""
try:
# PyInstaller 建立一個暫存資料夾並將路徑儲存在 _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# 將 base_path 設為指向根目錄
base_path = resource_path(".")
# 初始化 Pygame 所有模組
pygame.init()
pygame.init()
:這是啟動 Pygame 的關鍵指令。它會自動初始化所有 Pygame 需要的模組,例如圖形(display)、字體(font)和音效(mixer)等,是後續所有視覺與聽覺功能運作的基礎。resource_path
函式:這個函式是確保遊戲部署流暢性的關鍵。在開發時,我們可以透過相對路徑(如 "image/background.png"
)找到資源。然而,當使用 PyInstaller 將遊戲打包成執行檔(.exe)時,程式的執行環境會改變,相對路徑將會失效。此函式透過檢查 sys._MEIPASS
這個 PyInstaller 在執行時才會建立的特殊屬性,來智慧地判斷當前環境,並回傳正確的資源絕對路徑,確保遊戲無論在哪種環境下都能成功載入圖片、音效等檔案。遊戲視窗是玩家與遊戲世界互動的唯一介面,其尺寸與標題是帶給玩家的第一印象。
main.py
)# 螢幕常數
SCREEN_WIDTH = 1280
SCREEN_HEIGHT = 720
# 初始化 Pygame 視窗
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("奇幻卡牌競技場")
SCREEN_WIDTH
與 SCREEN_HEIGHT
:我們將視窗尺寸定義為常數,便於後續在程式碼中統一引用。1280x720 是一個常見的 16:9 寬螢幕解析度。pygame.display.set_mode((...))
:這個函式會根據傳入的元組 (寬, 高)
建立一個遊戲視窗物件,並將其賦值給 screen
變數。這個 screen
物件非常重要,它代表了主繪圖畫布,我們後續所有的繪圖操作都將在這個物件上進行。pygame.display.set_caption(...)
:此函式用於設定視窗頂部標題列的文字,有助於提升遊戲的品牌識別度。為了在遊戲中顯示中文提示、戰鬥日誌等資訊,我們需要載入一個支援中文的字體檔。
main.py
)# 載入中文字體
FONT_PATH = os.path.join(base_path, "msjh.ttf")
try:
FONT_LARGE = pygame.font.Font(FONT_PATH, 28)
FONT_MEDIUM = pygame.font.Font(FONT_PATH, 20)
# ... 其他字體大小
except FileNotFoundError:
print(f"Error: Font file not found... Using default system font.")
FONT_LARGE = pygame.font.SysFont("sans-serif", 28)
FONT_MEDIUM = pygame.font.SysFont("sans-serif", 20)
# ...
pygame.font.Font(font_path, size)
:這個函式用於從指定的字體檔案路徑(FONT_PATH
)載入字體,並設定其大小(size
),回傳一個字體物件。我們預先建立多個不同大小的字體物件,以便在 UI 中呈現不同層級的資訊,增加視覺層次感。try-except FileNotFoundError
:這是一個穩健性設計(Robustness)的體現。程式會嘗試載入 msjh.ttf
字體檔。如果檔案不存在並引發 FileNotFoundError
,except
區塊會被執行,程式將改用 pygame.font.SysFont
來呼叫系統預設字體。這確保了即使在缺少特定字體檔的情況下,遊戲依然可以正常顯示文字而不會崩潰,保障了流暢的使用者體驗。背景是營造遊戲氛圍、傳達世界觀的第一印象。
main.py
)try:
# 載入背景圖片
background_img = pygame.image.load(os.path.join(base_path, "image", "game_background.png"))
# 縮放圖片以符合視窗大小
background_img = pygame.transform.scale(background_img, (SCREEN_WIDTH, SCREEN_HEIGHT))
except pygame.error:
print("Warning: 'game_background.png' not found. Using a fallback background.")
# 創建一個純色表面作為備用背景
background_img = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
background_img.fill((30, 30, 30))
pygame.image.load(...)
:此函式用於從指定路徑載入一張圖片,並回傳一個 Surface 物件。pygame.transform.scale(...)
:載入的圖片原始尺寸可能與我們的視窗大小不符。這個函式可以將圖片(background_img
)縮放到指定的尺寸(SCREEN_WIDTH
, SCREEN_HEIGHT
),確保背景能完美填充整個視窗。try-except
結構。如果圖片檔 game_background.png
遺失,導致 Pygame 載入失敗,程式會建立一個純色的 pygame.Surface
物件作為備用背景。這同樣是為了防止遊戲因資源缺失而中斷,確保玩家體驗的穩定性。透過今天的學習,我們成功地為《奇幻卡牌競技場》搭建起了堅實的視覺基礎。一個設定得當的視窗、清晰的字體以及賞心悅目的背景,是吸引玩家沉浸其中的第一步。明天,我們將在這個畫布上,繪製更多核心的視覺元素,如卡牌、UI 圖示等,讓我們的奇幻世界更加栩栩如生!