|
|
7 months ago | |
|---|---|---|
| .. | ||
| README.md | 7 months ago | |
| assignment.md | 7 months ago | |
README.md
建造太空遊戲第一部分:簡介
journey
title 你的遊戲開發旅程
section 基礎
學習遊戲架構: 3: Student
了解繼承: 4: Student
探索組合: 4: Student
section 溝通
建立發布/訂閱系統: 4: Student
設計事件流程: 5: Student
連接元件: 5: Student
section 應用
創建遊戲物件: 5: Student
實作設計模式: 5: Student
規劃遊戲架構: 5: Student
就像 NASA 的任務控制中心在太空發射期間協調多個系統一樣,我們將建造一款太空遊戲,展示程式不同部分如何無縫協作。在創造你實際可以玩的東西時,你將學習適用於任何軟體專案的重要程式設計概念。
我們將探索兩種基本的程式碼組織方法:繼承和組合。這些不僅是學術概念——它們是推動從電子遊戲到銀行系統一切的相同模式。我們還將實現一種稱為發布/訂閱(pub/sub)的通訊系統,其運作方式類似於航天器中使用的通訊網路,允許不同元件共享資訊而不產生彼此依賴。
透過本系列結束時,你將了解如何構建可擴展且可演進的應用程式——無論你是在開發遊戲、網頁應用程式還是其他軟體系統。
mindmap
root((遊戲架構))
Object Organization
繼承
組合
類別繼承階層
行為混合
Communication Patterns
發佈/訂閱系統
事件發射器
訊息傳遞
鬆散耦合
Game Objects
屬性 (x, y)
行為 (移動, 碰撞)
生命週期管理
狀態管理
Design Patterns
工廠函數
觀察者模式
組件系統
事件驅動架構
Scalability
模組化設計
可維護程式碼
測試策略
性能優化
課前測驗
遊戲開發中的繼承與組合
隨著專案複雜度增加,程式碼組織變得關鍵。一開始可能只是簡單的腳本,但缺乏良好結構的話,會變得難以維護——就像阿波羅任務需要仔細協調成千上萬的元件一樣。
我們將探索兩種基本的程式碼組織方法:繼承與組合。每種方法都有其獨特優勢,理解兩者將幫助你在不同情況下選擇合適方法。我們將透過太空遊戲示範這些概念,在遊戲中,英雄、敵人、加成物和其他物件必須高效互動。
✅ 最著名的程式設計書籍中就有一本專注於設計模式。
在任何遊戲中,你都會碰到遊戲物件——遊戲世界中互動的元素。英雄、敵人、加成物與視覺特效都是遊戲物件。每個物件都存在於特定螢幕座標,使用x與y值,類似在座標平面繪點。
儘管外觀不同,這些物件通常有基本共同行為:
- 它們存在於某處——每個物件有 x 和 y 座標,遊戲才知道要畫在哪裡
- 許多會移動——英雄奔跑,敵人追逐,子彈飛過螢幕
- 它們有壽命——有些永遠存在,有些(例如爆炸)短暫出現後消失
- 它們對事件作出反應——當碰撞發生、取得加成物、血條更新
✅ 想想 Pac-Man 這款遊戲。你能在這遊戲中識別上面列出的四種物件類型嗎?
classDiagram
class GameObject {
+x: number
+y: number
+type: string
+exists_somewhere()
}
class MovableObject {
+moveTo(x, y)
+can_move_around()
}
class TemporaryObject {
+lifespan: number
+has_lifespan()
}
class InteractiveObject {
+onCollision()
+reacts_to_stuff()
}
GameObject <|-- MovableObject
GameObject <|-- TemporaryObject
GameObject <|-- InteractiveObject
MovableObject <|-- Hero
MovableObject <|-- Enemy
MovableObject <|-- Bullet
TemporaryObject <|-- PowerUp
TemporaryObject <|-- Explosion
InteractiveObject <|-- Collectible
InteractiveObject <|-- Obstacle
用程式碼表達行為
現在你了解遊戲物件共享的共同行為,我們來探討如何用 JavaScript 實現這些行為。你可以透過附加到類別或個別物件上的方法表達物件行為,有幾種方法可供選擇。
基於類別的方法
類別與繼承提供了一種結構化的方法來組織遊戲物件。像 Carl Linnaeus 開發的生物分類系統一樣,你先有一個包含共同屬性的基底類別,然後建立繼承基本特性並增加專門功能的子類別。
✅ 繼承是很重要的概念。詳細了解請看 MDN 繼承文章。
以下示範如何使用類別和繼承實作遊戲物件:
// 第一步:建立基礎的 GameObject 類別
class GameObject {
constructor(x, y, type) {
this.x = x;
this.y = y;
this.type = type;
}
}
一步步拆解:
- 我們創建了一個基礎範本供所有遊戲物件使用
- 建構子保存物件所在位置(
x,y)以及物件類型 - 這成為你所有遊戲物件建造的基礎
// 第2步:透過繼承新增移動功能
class Movable extends GameObject {
constructor(x, y, type) {
super(x, y, type); // 呼叫父類別建構子
}
// 新增移動至新位置的能力
moveTo(x, y) {
this.x = x;
this.y = y;
}
}
以上程式我們:
- 擴展了 GameObject 類別,新增移動功能
- 使用
super()呼叫父建構子以初始化繼承屬性 - 新增
moveTo()方法更新物件位置
// 第3步:建立特定的遊戲物件類型
class Hero extends Movable {
constructor(x, y) {
super(x, y, 'Hero'); // 自動設定類型
}
}
class Tree extends GameObject {
constructor(x, y) {
super(x, y, 'Tree'); // 樹木不需要移動
}
}
// 第4步:使用你的遊戲物件
const hero = new Hero(0, 0);
hero.moveTo(5, 5); // 英雄可以移動!
const tree = new Tree(10, 15);
// tree.moveTo() 會造成錯誤-樹木無法移動
理解這些概念:
- 創造繼承適當行為的專門物件類型
- 展示繼承如何允許選擇性地加入功能
- 說明英雄會移動,樹木則保持靜止
- 解釋類別層級防止不當動作發生
✅ 花幾分鐘重新想像 Pac-Man 英雄(例如 Inky、Pinky 或 Blinky)如何用 JavaScript 寫出。
組合方法
組合遵循模組化設計哲學,類似於工程師設計航天器時使用可互換元件。你不從父類繼承,而是混合特定行為來創造具備所需功能的物件。此方法提供彈性,沒有嚴格層級限制。
// 步驟1:建立基本行為物件
const gameObject = {
x: 0,
y: 0,
type: ''
};
const movable = {
moveTo(x, y) {
this.x = x;
this.y = y;
}
};
這段程式碼作用:
- 定義基底
gameObject含位置與類型屬性 - 建立獨立的
movable行為物件提供移動功能 - 將位置數據與移動邏輯分開,解耦
// 步驟 2:透過組合行為來組合物件
const movableObject = { ...gameObject, ...movable };
// 步驟 3:為不同物件類型建立工廠函式
function createHero(x, y) {
return {
...movableObject,
x,
y,
type: 'Hero'
};
}
function createStatic(x, y, type) {
return {
...gameObject,
x,
y,
type
};
}
以上程式我們:
- 用展開語法結合基底物件屬性與移動行為
- 創建回傳客製物件的工廠函式
- 實現無階級結構的彈性物件創建
- 允許物件擁有其恰當的行為組合
// 第4步:創建並使用您的組合物件
const hero = createHero(10, 10);
hero.moveTo(5, 5); // 運作完美!
const tree = createStatic(0, 0, 'Tree');
// tree.moveTo() 未定義 - 沒有組合移動行為
關鍵重點:
- 透過混合行為來組合物件,而非繼承
- 比嚴格繼承層級更具彈性
- 讓物件只有它們需要的特性
- 使用現代 JavaScript 展開語法清理物件結合
**Which Pattern Should You Choose?**
**Which Pattern Should You Choose?**
```mermaid
quadrantChart
title Code Organization Patterns
x-axis Simple --> Complex
y-axis Rigid --> Flexible
quadrant-1 Advanced Composition
quadrant-2 Hybrid Approaches
quadrant-3 Basic Inheritance
quadrant-4 Modern Composition
Class Inheritance: [0.3, 0.2]
Interface Implementation: [0.6, 0.4]
Mixin Patterns: [0.7, 0.7]
Pure Composition: [0.8, 0.9]
Factory Functions: [0.5, 0.8]
Prototype Chain: [0.4, 0.3]
💡 專家小技巧:這兩種模式在現代 JavaScript 開發中都有應用。類別適合明確定義的層級結構,組合則適合最大彈性的需求。
何時使用哪一種:
- 有明確「是個」關係時選用繼承(英雄 是個 可移動物件)
- 當需要「擁有」關係時選擇組合(英雄 擁有 移動能力)
- 考慮團隊偏好與專案要求
- 記得可以在同一應用中混用兩種方式
🔄 教學自我檢測
物件組織理解:在進入通訊模式前,確保你可以:
- ✅ 解釋繼承與組合的差異
- ✅ 判斷何時使用類別 vs 工廠函式
- ✅ 了解繼承中
super()怎麼運作 - ✅ 認識兩種方式對遊戲開發的優點
快速自測:如何用這兩種方法創建一個能移動且會飛的敵人?
- 繼承方式:
class FlyingEnemy extends Movable - 組合方式:
{ ...movable, ...flyable, ...gameObject }
實務連結:這些模式隨處可見:
- React Components:屬性(組合)vs 類別繼承
- 遊戲引擎:實體-組件系統採用組合
- 行動應用程式:UI 框架常用繼承層級
通訊模式:發布/訂閱系統
隨著應用愈發龐大,管理元件間通訊成挑戰。發布/訂閱模式利用類似無線廣播原理——一個發送者可以觸及多個接收者,且發送者不需知道誰在聽。
想想當英雄受傷時發生什麼:血條更新、音效撥放、視覺反饋出現。與其讓英雄物件直接耦合這些系統,pub/sub 允許英雄廣播「受傷」訊息。任何需要回應的系統都可以訂閱該訊息類型並作出反應。
✅ Pub/Sub 是「發布-訂閱」的縮寫。
flowchart TD
A[英雄受到傷害] --> B[發布:HERO_DAMAGED]
B --> C[事件系統]
C --> D[血量條訂閱者]
C --> E[音效系統訂閱者]
C --> F[視覺效果訂閱者]
C --> G[成就系統訂閱者]
D --> H[更新血量顯示]
E --> I[播放受傷音效]
F --> J[顯示紅色閃光]
G --> K[檢查存活成就]
style A fill:#ffebee
style B fill:#e1f5fe
style C fill:#e8f5e8
style H fill:#fff3e0
style I fill:#fff3e0
style J fill:#fff3e0
style K fill:#fff3e0
理解 Pub/Sub 架構
pub/sub 模式讓應用不同部分鬆散耦合,意即它們能配合運作,卻非彼此直接依賴。此分離使程式碼更易維護、測試且彈性高。
pub/sub 重要角色:
- 訊息——簡單標籤類似
'PLAYER_SCORED'描述發生了什麼(可帶額外資訊) - 發布者——負責「事情發生了!」訊息傳出給關注者
- 訂閱者——表示「對該事件有興趣」並在事件發生時作出反應的物件
- 事件系統——中介者確保訊息送達正確的聽眾
建立事件系統
讓我們創建簡單但強大的事件系統示範以上概念:
// 第一步:建立 EventEmitter 類別
class EventEmitter {
constructor() {
this.listeners = {}; // 儲存所有事件監聽器
}
// 為特定的訊息類型註冊監聽器
on(message, listener) {
if (!this.listeners[message]) {
this.listeners[message] = [];
}
this.listeners[message].push(listener);
}
// 向所有已註冊的監聽器傳送訊息
emit(message, payload = null) {
if (this.listeners[message]) {
this.listeners[message].forEach(listener => {
listener(message, payload);
});
}
}
}
程式運作分析:
- 創建中心事件管理系統使用簡單類別
- 使用物件以訊息類型分類儲存監聽器
- 以
on()註冊新監聽器 - 用
emit()向所有相關監聽器廣播訊息 - 支援可選數據載荷傳遞相關資訊
實做範例
來看看實際應用!我們打造簡單移動系統,展示 pub/sub 乾淨且彈性的特色:
// 第一步:定義您的訊息類型
const Messages = {
HERO_MOVE_LEFT: 'HERO_MOVE_LEFT',
HERO_MOVE_RIGHT: 'HERO_MOVE_RIGHT',
ENEMY_SPOTTED: 'ENEMY_SPOTTED'
};
// 第二步:建立您的事件系統和遊戲物件
const eventEmitter = new EventEmitter();
const hero = createHero(0, 0);
程式碼功能簡述:
- 定義常數物件避免訊息名稱拼寫錯誤
- 創建事件發射器物件處理通訊
- 初始化英雄物件於起始位置
// 第三步:設置事件監聽器(訂閱者)
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
hero.moveTo(hero.x - 5, hero.y);
console.log(`Hero moved to position: ${hero.x}, ${hero.y}`);
});
eventEmitter.on(Messages.HERO_MOVE_RIGHT, () => {
hero.moveTo(hero.x + 5, hero.y);
console.log(`Hero moved to position: ${hero.x}, ${hero.y}`);
});
以上程式我們:
- 註冊事件監聽器回應移動訊息
- 根據移動方向更新英雄位置
- 新增控制台日誌追蹤英雄位置
- 將移動邏輯從輸入處理分離
// 第4步:將鍵盤輸入連接到事件(發布者)
window.addEventListener('keydown', (event) => {
switch(event.key) {
case 'ArrowLeft':
eventEmitter.emit(Messages.HERO_MOVE_LEFT);
break;
case 'ArrowRight':
eventEmitter.emit(Messages.HERO_MOVE_RIGHT);
break;
}
});
理解這些概念:
- 連接鍵盤輸入與遊戲事件,無需緊耦合
- 讓輸入系統間接與遊戲物件通訊
- 允許多系統回應同一鍵盤事件
- 便於更換按鍵配置或添入新輸入方法
sequenceDiagram
participant User
participant Keyboard
participant EventEmitter
participant Hero
participant SoundSystem
participant Camera
User->>Keyboard: 按下向左箭頭
Keyboard->>EventEmitter: emit('HERO_MOVE_LEFT')
EventEmitter->>Hero: 向左移動5像素
EventEmitter->>SoundSystem: 播放腳步聲
EventEmitter->>Camera: 跟隨英雄
Hero->>Hero: 更新位置
SoundSystem->>SoundSystem: 播放音效
Camera->>Camera: 調整視窗
💡 專家小技巧:此模式美妙之處在於彈性!你能簡單地添入音效、畫面震動或粒子效果,只需加更多事件監聽器,無須修改現有鍵盤或移動程式碼。
這就是你會喜歡此方法的理由:
- 新增功能變得超簡單,只要監聽你關注的事件
- 多個系統能對同一事件產生反應,互不干擾
- 測試更容易,因為各部分獨立運作
- 出錯時明確知道該從哪裡找問題
為什麼 Pub/Sub 可有效擴展
Pub/sub 模式在應用複雜度提升時仍維持簡潔。無論管理數十個敵人、動態 UI 更新或音效系統,該模式能在不改變架構下應對更大規模。新功能輕鬆整合進既有事件系統,不影響現有功能。
⚠️ 常見錯誤:剛開始別創造過多特定訊息類型。先用大類別,之後根據遊戲需求細化。
最佳實作建議:
- 將相關訊息分組歸類
- 使用清楚描述發生事件的名稱
- 使訊息載荷簡潔聚焦
- 為團隊協作做好訊息類型文件化
🔄 教學自我檢測
事件驅動架構理解:檢驗你對系統完整概念的掌握:
- ✅ Pub/sub 如何避免組件間緊耦合?
- ✅ 為何事件驅動使新增功能更簡單?
- ✅ EventEmitter 在通訊流程中扮演什麼角色?
- ✅ 訊息常數如何避免錯誤並提升維護性?
設計挑戰:你會如何用 pub/sub 處理以下遊戲場景?
- 敵人死亡:更新分數、撥放音效、生成加成道具、從畫面移除
- 關卡完成:停止音樂、顯示介面、存檔進度、載入下一關
- 加成物被收集:提升能力、更新 UI、撥放效果、啟動計時器
專業連結:此模式廣泛應用於:
- 前端框架:React/Vue 事件系統
- 後端服務:微服務通訊
- 遊戲引擎:Unity 事件系統
- 行動開發:iOS/Android 通知系統
GitHub Copilot Agent 挑戰 🚀
使用 Agent 模式完成以下挑戰:
描述: 建立簡單遊戲物件系統,結合繼承與 pub/sub 模式。實作基礎遊戲,讓不同物件能透過事件通訊,不需彼此直接認識。
提示: 用 JavaScript 建立遊戲系統,要求如下:1) 創建含 x, y 座標與 type 屬性的基礎 GameObject 類別。2) 創建可移動的 Hero 類別繼承 GameObject。3) 創建可追逐英雄的 Enemy 類別繼承 GameObject。4) 實作用於 pub/sub 模式的 EventEmitter 類別。5) 設置事件監聽器,當英雄移動時,附近敵人士接收到 'HERO_MOVED' 事件並更新位置向英雄靠近。加入 console.log 來顯示物件間通訊。
了解更多agent 模式資訊。
🚀 挑戰
考慮 pub-sub 模式如何增強遊戲架構。識別哪些元件應該發送事件以及系統應如何響應。設計一個遊戲概念並繪製其元件之間的通訊模式。
課後測驗
複習與自學
透過閱讀相關內容,深入了解 Pub/Sub。
⚡ 您可以在接下來的 5 分鐘內做什麼
- 開啟任意 HTML5 線上遊戲並使用開發者工具檢查其程式碼
- 建立一個簡單的 HTML5 Canvas 元素並繪製基本形狀
- 試用
setInterval創建簡單動畫迴圈 - 探索 Canvas API 文件並試用繪圖方法
🎯 您可以在這一小時內完成什麼
- 完成課後測驗並理解遊戲開發概念
- 建立含 HTML、CSS 和 JavaScript 檔案的遊戲專案結構
- 建立一個持續更新和渲染的基本遊戲迴圈
- 在畫布上繪製第一個遊戲精靈
- 實作基本的圖像與音效資產載入
📅 您的一週遊戲製作計畫
- 完成全部預定功能的太空遊戲
- 新增精緻的圖形、音效與流暢動畫
- 實作遊戲狀態(開始畫面、遊戲中、遊戲結束)
- 建立計分系統及玩家進度追蹤
- 使遊戲可以跨裝置響應並兼顧無障礙性
- 線上分享遊戲並蒐集玩家回饋
🌟 您的一個月遊戲開發計畫
- 製作多款遊戲,探索不同類型與機制
- 學習 Phaser 或 Three.js 等遊戲開發框架
- 參與開源遊戲開發專案
- 精通進階遊戲程式設計模式與優化技巧
- 建立展示遊戲開發技能的作品集
- 指導對遊戲開發與互動媒體感興趣的新人
🎯 您的遊戲開發精通時間表
timeline
title 遊戲架構學習進程
section 物件模式(20分鐘)
程式碼組織:類別繼承
:組合模式
:工廠函式
:行為混合
section 通訊系統(25分鐘)
事件架構:發布/訂閱實作
:訊息設計
:事件觸發器
:鬆散耦合
section 遊戲物件設計(30分鐘)
實體系統:屬性管理
:行為組合
:狀態處理
:生命週期管理
section 架構模式(35分鐘)
系統設計:組件系統
:觀察者模式
:命令模式
:狀態機
section 進階概念(45分鐘)
可擴展架構:效能優化
:記憶體管理
:模組化設計
:測試策略
section 遊戲引擎概念(一週)
專業發展:場景圖
:資產管理
:渲染流程
:物理整合
section 框架精通(兩週)
現代遊戲開發:React 遊戲模式
:Canvas 優化
:WebGL 基礎
:進階網頁應用遊戲
section 業界實務(一個月)
專業技能:團隊合作
:程式碼審查
:遊戲設計模式
:效能剖析
🛠️ 您的遊戲架構工具組總結
完成本課程後,您已具備:
- 設計模式精通:理解繼承與組合的取捨
- 事件驅動架構:Pub/sub 實作以支援可擴充通訊
- 物件導向設計:類別繼承與行為組合
- 現代 JavaScript:工廠函式、展開語法及 ES6+ 模式
- 可擴充架構:鬆耦合與模組化設計原則
- 遊戲開發基礎:實體系統與元件模式
- 專業模式:業界標準程式碼組織方法
實務應用:這些模式可直接應用於:
- 前端框架:React/Vue 元件架構及狀態管理
- 後端服務:微服務通訊與事件驅動系統
- 行動開發:iOS/Android 應用架構與通知系統
- 遊戲引擎:Unity、Unreal 以及 Web 遊戲開發
- 企業軟體:事件溯源與分散式系統設計
- API 設計:RESTful 服務及即時通訊
專業技能獲得:您現在能夠:
- 設計 使用已驗證模式的可擴充軟體架構
- 實作 處理複雜互動的事件驅動系統
- 選擇 適當的程式碼組織策略因應不同場景
- 除錯 與維護鬆耦合系統的效率提升
- 溝通 使用業界標準術語說明技術決策
下一階段:您已準備好將這些模式應用於真實遊戲,探索進階遊戲開發主題,或在 Web 應用中實踐這些架構概念!
🌟 成就解鎖:您已掌握從簡單遊戲到複雜企業系統所需的基本軟體架構模式!
作業
免責聲明:
本文件係使用 AI 翻譯服務 Co-op Translator 翻譯而成。雖然我們力求準確,但請注意自動翻譯可能包含錯誤或不準確之處。原始文件之原文版本應視為權威來源。對於重要資訊,建議採用專業人工翻譯。我們不對因使用本翻譯所導致之任何誤解或誤釋負責。
