Skip to content

About

基於 Python 與 Pygame 的Tetris遊戲實作專案。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tetris (俄羅斯方塊) - Pygame 實作教學專案

Python Pygame License

本專案為2025 中山資工營之遊戲實作課程教材。
營隊課程以 Python 與 Pygame 遊戲引擎為主軸,帶領學員從零打造具備完整方塊旋轉、碰撞檢測、暫存、預覽、滿行消除與硬降功能的經典俄羅斯方塊遊戲。
透過本教材,學員能夠深入理解遊戲主迴圈、二維陣列地圖管理、物件導向程式設計以及離散坐標系中的碰撞檢測演算法。


目錄 (Table of Contents)


專案特色

  1. 經典規則完整實作:
    • 支援 7 種經典四格骨牌(I、J、L、O、S、T、Z)及其專屬配色。
    • 實作順時針旋轉、軟降(Soft Drop)、硬降(Hard Drop)、左右橫移。
    • 具備方塊暫存(Hold)與下一個方塊預覽(Next)功能。
  2. 直觀的物件導向設計(OOP & Pygame):
    • 使用 Tetromino 類別繼承 pygame.sprite.Sprite 封裝單一方塊的狀態(種類、旋轉角、位置座標、著地延遲計數)。
    • 模組化拆分遊戲主迴圈、方塊邏輯、地圖資料與全域設定。
  3. 穩健的離散碰撞檢測(Discrete Collision Detection):
    • 在方塊進行任何平移或旋轉操作時,先一步預判邊界(左、右、底)及是否與盤面上已固定的方塊重疊,若發生衝突則自動退回前一合法狀態。
  4. 貼近真實機制的著地延遲(Lock Delay / Hit Bottom Delay):
    • 方塊接觸底部或下方障礙時不會立刻定型,提供緩衝時間讓玩家進行最後微調,提升遊戲手感。
  5. 高度可自訂性:
    • 集中於 Setting.py 統一管理落下速度、移動冷卻、視窗大小與網格尺寸,方便教學展示與難度調整。

遊戲操作說明

按鍵 動作名稱 功能說明
↑ (上方向鍵) 旋轉 (Rotate) 將目前方塊順時針旋轉 90 度(若旋轉後會穿牆或重疊則取消旋轉)
↓ (下方向鍵) 軟降 (Soft Drop) 按住可加速方塊向下墜落
← / → (左右方向鍵) 水平移動 (Move) 向左或向右移動一格(內建冷卻間隔,防止滑動過快失控)
Space (空白鍵) 硬降 (Hard Drop) 瞬間讓方塊直接垂直落到底部
Z 鍵 暫存方塊 (Hold) 將當前方塊暫存至 Hold 區,或與 Hold 區內的方塊進行調換
關閉視窗 (X) 退出 (Quit) 結束主迴圈並關閉遊戲程式

專案目錄結構

Tetris-pygame/
├── Game.py             # 遊戲主程式:包含遊戲主迴圈、事件處理、消除行與主要畫面繪製
├── Tetrominoes.py      # 方塊物件與核心邏輯:方塊類別、位移、旋轉、落下判定、Hold 交換
├── Tmap.py             # 資料定義:7 種方塊顏色 (TCOLOR) 與 4 方向旋轉矩陣 (TMAP)
└── Setting.py          # 參數設定:遊戲區行列數、格點大小、FPS、下落頻率等常數

核心架構與檔案職責

flowchart TD
    subgraph Setting.py
        S[常數與參數設定<br/>WIDTH, HEIGHT, FPS, INTERVAL]
    end

    subgraph Tmap.py
        TM[形狀定義 TMAP<br/>顏色定義 TCOLOR]
    end

    subgraph Tetrominoes.py
        T[Tetromino 類別<br/>旋轉 / 移動 / 碰撞判斷]
        PF[二維陣列 play_field<br/>儲存固定後的盤面方塊]
        DU[dropUpdate & hold 函式]
    end

    subgraph Game.py
        GL[遊戲主迴圈 main<br/>事件監聽 Event Handling]
        RA[消除整行 RemoveALine]
        REN[畫面渲染 Render]
    end

    S --> Tetrominoes.py
    S --> Game.py
    TM --> Tetrominoes.py
    Tetrominoes.py --> Game.py
Loading
  • Setting.py: 集中管理遊戲各項物理與介面常數,包含網格大小(UNIT_LENGTH = 30)、盤面尺寸(寬 10 格、高 20 格)、更新幀率(FPS = 60)、落下週期(DROP_INTERVAL = 10)等。
  • Tmap.py: 純資料定義模組。定義了 7 種四格骨牌的 RGB 顏色(TCOLOR)以及各方塊在 4 種旋轉角度下的 4×4 二維陣列布林遮罩(TMAP)。
  • Tetrominoes.py: 核心邏輯模組。建立全域盤面陣列 play_field(10×24);實作 Tetromino 物件導向類別(負責旋轉、移動、碰撞檢測與自身繪製);提供方塊自然落下判定(dropUpdate)與暫存置換(hold)。
  • Game.py: 遊戲啟動入口。負責 Pygame 視窗初始化、處理鍵盤事件、主遊戲迴圈計時更新、消行邏輯(RemoveALine)以及組合所有畫面元件進行最終渲染。

核心演算法與實作原理解析

1. 坐標系轉換與頂部緩衝區

遊戲區域(Playfield)邏輯尺寸為:寬 10 格($WIDTH = 10$)、高 20 格($HEIGHT = 20$)。

頂部緩衝設計(+4 列)

為了讓方塊能夠在進入可見視窗前順利生成並旋轉,盤面陣列高度定義為 $HEIGHT + 4 = 24$ 列:

  • $j \in [0, 3]$:畫面頂部之上的隱藏生成緩衝區。方塊初始位置為 $(x=4, y=-3)$。
  • $j \in [4, 23]$:玩家在視窗中實際看見的可視遊戲區域。

座標映射公式

當邏輯格點座標為 $(x, y)$ 時,映射到 Pygame 視窗像素座標如下:

  • 主遊戲區像素座標: $$pixel_x = (x + 1) \times UNIT_LENGTH$$ $$pixel_y = (y + 1) \times UNIT_LENGTH$$
  • 盤面陣列索引對應: $$play_field[x][y + 4]$$

2. 四格骨牌(Tetromino)與 4×4 旋轉矩陣

在 Tmap.py 中,每一種骨牌皆以一個 $4 \times 4$ 的二維陣列表示,並預先定義好 4 種旋轉朝向($0^\circ, 90^\circ, 180^\circ, 270^\circ$):

以 T 方塊為例 (4 種朝向狀態):
   朝向 0          朝向 1          朝向 2          朝向 3
[0, 1, 0, 0]    [0, 1, 0, 0]    [0, 0, 0, 0]    [0, 1, 0, 0]
[1, 1, 1, 0]    [0, 1, 1, 0]    [1, 1, 1, 0]    [1, 1, 0, 0]
[0, 0, 0, 0]    [0, 1, 0, 0]    [0, 1, 0, 0]    [0, 1, 0, 0]
[0, 0, 0, 0]    [0, 0, 0, 0]    [0, 0, 0, 0]    [0, 0, 0, 0]

旋轉與回溯(Rollback)機制

def rotate(self) -> None:
    self.rotation = (self.rotation + 1) % 4
    if self.Iscollision():
        # 若旋轉後發生碰撞,復原角度
        self.rotation = (self.rotation - 1) % 4

當玩家按下旋轉時,先樂觀更新 self.rotation,若呼叫 Iscollision() 發現穿牆或卡入既有方塊,則立刻退回原角度,確保合法性。


3. 邊界與重疊碰撞檢測演算法

在 Tetromino.Iscollision 中,會歷遍 $4 \times 4$ 矩陣中值為 1 的每一個小方塊:

flowchart TD
    Start(["開始碰撞檢查"]) --> Loop["遍歷 4x4 矩陣中的每一格"]
    Loop --> CheckBit{"該位置是否有方塊?"}
    CheckBit -- 否 --> NextCell["檢查下一格"]
    CheckBit -- 是 --> CheckBound{"是否超出邊界?<br/>(超出左、右邊界或底部)"}
    CheckBound -- 是 --> Collide(["判定碰撞: True"])
    CheckBound -- 否 --> CheckField{"盤面該位置是否已被佔用?<br/>(play_field 該座標已有方塊)"}
    CheckField -- 是 --> Collide
    CheckField -- 否 --> NextCell
    NextCell --> AllDone{"是否檢查完畢?"}
    AllDone -- 否 --> Loop
    AllDone -- 是 --> Safe(["判定無碰撞: False"])
Loading

若任何一個小單元超出左界、右界、底界,或該格在 play_field 中已被其他方塊佔用,立即回傳 True。


4. 著陸鎖定與延遲機制 (Lock Delay)

為了避免方塊一接觸到地板就瞬間凝固導致玩家無法進行滑移或旋轉調整,程式實作了 HitBtmCnt 計數機制:

  1. 方塊向下嘗試移動一格。
  2. 若發生碰撞,退回前一格,並將著底計數 HitBtmCnt += 1。
  3. 只有當 HitBtmCnt >= HITBTM_DELAY(預設為 5 次檢查)時,才正式將方塊寫入 play_field 陣列固定。
  4. 固定時若發現任何小單元位於頂部緩衝區($y < 0$),即判定為堆疊超出上限,觸發 Game Over。

5. 消除整行演算法 (Line Clear)

每次方塊降落固定後,呼叫 RemoveALine() 進行滿行判定與清理:

def RemoveALine() -> None:
    for y in range(HEIGHT):
        hasAline = True
        for x in range(WIDTH):
            if not play_field[x][y + 4]:
                hasAline = False
                break
        if hasAline:
            # 從該行開始,逐行將上方的內容向下覆蓋搬移
            for j in range(y, 0, -1):
                for i in range(WIDTH):
                    play_field[i][j + 4] = play_field[i][j - 1 + 4]
            # 最頂部的一行補空 (0)
            for i in range(WIDTH):
                play_field[i][0 + 4] = 0
  • 滿行檢測:由上至下掃描每一橫行,若任一行所有 10 格皆非 0,即表示整行填滿。
  • 重力下推:將該行上方的每一行向下拷貝一列($j \to j+1$),並將第 0 行清空重置。

6. 方塊暫存機制 (Hold)

當玩家按下 Z 鍵時,觸發 hold 函式:

  • 交換當前的 DropingTetr 與暫存區的 HoldTetr。
  • 被換出的方塊會重置座標至頂部生成位置 $(INIT_X, INIT_Y)$,重新開始下落。
  • 右側介面的 Hold 區域將同步重繪最新暫存方塊。

快速開始 (Quick Start)

1. 環境需求與套件安裝

本專案支援 Python 3.8 或以上版本,僅需安裝官方 pygame 套件:

# 安裝 pygame
pip install pygame

2. 啟動遊戲

進入專案根目錄並執行 Game.py:

# 執行俄羅斯方塊主程式
python Game.py

啟動後即可在跳出的 Pygame 視窗中透過鍵盤開始遊玩!


遊戲參數自訂 (Setting.py)

學員可以自由修改 Setting.py 中的各項常數,體驗不同的遊戲手感或自訂遊戲介面:

參數名稱 預設值 說明 調整效果
UNIT_LENGTH 30 主遊戲區每格像素邊長 放大可使遊戲視窗整體按比例變大
SMALL_UNIT_LENGTH 25 側邊欄(Hold/Next)格子像素邊長 控制預覽方塊的顯示尺寸
WIDTH 10 遊戲區橫向網格數 修改可改變棋盤寬度(標準規則為 10)
HEIGHT 20 遊戲區縱向網格數 修改可改變棋盤高度(標準規則為 20)
FPS 60 畫面更新率 (Frames Per Second) 控制主迴圈每秒更新次數
DROP_INTERVAL 10 方塊自動下落間隔 (幀數) 數值愈小下落速度愈快,難度愈高
HITBTM_DELAY 5 著地延遲鎖定閾值 數值愈大著地後可調整的時間愈長
CONTROL_INTERVAL 7 左右移動冷卻幀數 控制橫移時的按鍵連發靈敏度
WIN_BACKGROUND_COLOR (50, 50, 50) 視窗背景 RGB 顏色 可調整視窗周圍背景色彩

學員課後延伸挑戰 (Bonus Challenges)

本教材架構清晰、模組分明,非常適合作為學員在營隊結束後的自主探索專案。歡迎挑戰以下功能擴充:

  • 計分與等級系統 (Score & Level Progression):
    • 根據單次消除行數(單行 Single、雙行 Double、三行 Triple、四行 Tetris)給予階梯式加分。
    • 當消除總行數達到門檻時升級(Level Up),並調小 DROP_INTERVAL 使方塊越落越快。
  • 幽靈方塊 (Ghost Piece):
    • 在方塊正下方繪製半透明或虛線框,預先標示硬降(Hard Drop)落點,輔助玩家瞄準。
  • 音效與背景音樂 (Sound Effects & BGM):
    • 加入旋轉、硬降、消行與 Game Over 音效,以及經典的俄羅斯方塊 8-bit 背景旋律。
  • Hold 鎖定防刷機制 (Hold Lock):
    • 實作經典標準規則:每一次方塊落定前,只能使用一次 Hold,避免玩家無限次來回交換方塊。
  • 排行榜或最高分紀錄 (High Score Persistence):
    • 使用 Python 檔案 I/O(如 JSON 或文字檔)保存本機歷史最高紀錄,並在側邊欄即時呈現。

About

基於 Python 與 Pygame 的Tetris遊戲實作專案。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages