日韩偷拍一区二区,国产香蕉久久精品综合网,亚洲激情五月婷婷,欧美日韩国产不卡

在線客服
設計模式與游戲開發圖書
人氣:29

設計模式與游戲開發

十年磨一劍,作者將設計模式理論巧妙地融入到實踐中,以一個游戲的完整實現呈現設計模式的應用及經驗的傳承

內容簡介

《設計模式與游戲開發》是作者“十年磨一劍”,將設計模式理論巧妙地融合到實踐中的教材。 全書采用了整合式的項目教學,即以一個游戲的范例來應用23種設計模式的實現貫穿全書,讓讀者學習到整個游戲開發的全過程和作者想要傳承的經驗,并以淺顯易懂的比喻來解析難以理解的設計模式,讓想深入了解此領域的讀者更加容易上手。 本書既可以作為大學、專科和職業院校游戲程序設計專業的教材,也可以作為游戲從業人員提高游戲設計能力和規范運用設計模式的培訓教材,還可以作為有這方面職業興趣的讀者學習和提高的自學參考書。

編輯推薦

十年磨一劍,作者將設計模式理論巧妙地融入到實踐中,以一個游戲的完整實現呈現設計模式的應用及經驗的傳承 《軒轅劍》之父——蔡明宏、博學游戲制作人——李佳澤、Product Evangelist at Unity Technologies——Kelvin Lo、信仁軟件設計創辦人—— 賴信仁、博學3D游戲美術——劉明愷 聯合推薦全書采用了整合式的項目教學,即以一個游戲的范例來應用23種設計模式的實現貫穿全書,讓讀者學習到整個游戲開發的全過程和作者想要傳承的經驗,并以淺顯易懂的比喻來解析難以理解的設計模式,讓想深入了解此領域的讀者更加容易上手。

作者簡介

蔡升達當年為實現游戲夢從學術界進入游戲業,累積了10年游戲開發經驗,包含多款大型多人線上游戲(MMORPG)、網頁游戲(Web Game)、移動平臺連線游戲(APP Game)。曾任職于臺灣地區知名游戲開發公司,擔任游戲設計師、專案程序統籌、研發技術中心經理等職務,現任知名新創團隊研發總監一職。擅長游戲程序設計、網絡程序設計、分布式系統設計、電腦圖學、影像搜索、游戲制作規劃及運作、游戲專案管理。喜歡閱讀,家中有上千本藏書,包含信息技術、文學、奇幻小說、歷史小說等,因為看了很多,所以也有很多想法想與人分享。構想多年之后,某日下午終于下筆開始了這本書。十年磨一劍,作者將設計模式理論巧妙地融入到實踐中,以一個游戲的完整實現呈現設計模式的應用及經驗的傳承

目錄

第1篇 設計模式與游戲設計

第1章 游戲實現中的設計模式 2

1.1 設計模式的起源 2

1.2 軟件的設計模式是什么? 3

1.3 面向對象設計中常見的設計原則 4

1.4 為什么要學習設計模式 7

1.5 游戲程序設計與設計模式 8

1.6 模式的應用與學習方式 10

1.7 結論 11

第2章 游戲范例說明 12

2.1 游戲范例 12

2.2 GoF的設計模式范例 15

第2篇 基礎系統

第3章 游戲場景的轉換——狀態模式(State) 20

3.1 游戲場景 20

3.1.1 場景的轉換 20

3.1.2 游戲場景可能的實現方式 23

3.2 狀態模式(State) 24

3.2.1 狀態模式(State)的定義 24

3.2.2 狀態模式(State)的說明 25

3.2.3 狀態模式(State)的實現范例 25

3.3 使用狀態模式(State)實現游戲場景的轉換 28

3.3.1 SceneState的實現 28

3.3.2 實現說明 29

3.3.3 使用狀態模式(State)的優點 35

3.3.4 游戲執行流程及場景轉換說明 36

3.4 狀態模式(State)面對變化時 37

3.5 結論 37

第4章 游戲主要類——外觀模式(Facade) 39

4.1 游戲子功能的整合 39

4.2 外觀模式(Facade) 41

4.2.1 外觀模式(Facade)的定義 41

4.2.2 外觀模式(Facade)的說明 42

4.2.3 外觀模式(Facade)的實現說明 43

4.3 使用外觀模式(Facade)實現游戲主程序 44

4.3.1 游戲主程序架構設計 44

4.3.2 實現說明 45

4.3.3 使用外觀模式(Facade)的優點 47

4.3.4 實現外觀模式(Facade)時的注意事項 48

4.4 外觀模式(Facade)面對變化時 48

4.5 結論 48

第5章 獲取游戲服務的對象——單例模式(Singleton) 50

5.1 游戲實現中的對象 50

5.2 單例模式(Singleton) 51

5.2.1 單例模式(Singleton)的定義 51

5.2.2 單例模式(Singleton)的說明 51

5.2.3 單例模式(Singleton)的實現范例 52

5.3 使用單例模式(Singleton)獲取的游戲服務對象 53

5.3.1 游戲服務類的單例模式實現 53

5.3.2 實現說明 54

5.3.3 使用單例模式(Singleton)后的比較 55

5.3.4 反對使用單例模式(Singleton)的原因 55

5.4 少用單例模式(Singleton)時如何方便地引用到單一對象 58

5.5 結論 63

第6章 游戲內各系統的整合——中介者模式(Mediator) 64

6.1 游戲系統之間的溝通 64

6.2 中介者模式(Mediator) 68

6.2.1 中介者模式(Mediator)的定義 69

6.2.2 中介者模式(Mediator)的說明 69

6.2.3 中介者模式(Mediator)的實現范例 69

6.3 中介者模式(Mediator)作為系統之間的溝通接口 72

6.3.1 使用中介者模式(Mediator)的系統架構 73

6.3.2 實現說明 73

6.3.3 使用中介者模式(Mediator)的優點 79

6.3.4 實現中介者模式(Mediator)時的注意事項 79

6.4 中介者模式(Mediator)面對變化時 80

6.5 結論 80

第7章 游戲的主循環——Game Loop 82

7.1 GameLoop由此開始 82

7.2 怎么實現游戲循環(Game Loop) 84

7.3 在Unity3D中實現游戲循環 85

7.4 P級陣地的游戲循環 89

7.5 結論 92

第3篇 角色的設計

第8章 角色系統的設計分析 94

8.1 游戲角色的架構 94

8.2 角色類的規劃 95

第9章 角色與武器的實現——橋接模式(Bridge) 98

9.1 角色與武器的關系 98

9.2 橋接模式(Bridge) 103

9.2.1 橋接模式(Bridge)的定義 103

9.2.2 橋接模式(Bridge)的說明 107

9.2.3 橋接模式(Bridge)的實現范例 108

9.3 使用橋接模式(Bridge)實現角色與武器接口 110

9.3.1 角色與武器接口設計 110

9.3.2 實現說明 111

9.3.3 使用橋接模式(Bridge)的優點 116

9.3.4 實現橋接模式(Bridge)的注意事項 116

9.4 橋接模式(Bridge)面對變化時 116

9.5 結論 117

第10章 角色屬性的計算——策略模式(Strategy) 118

10.1 角色屬性的計算需求 118

10.2 策略模式(Strategy) 121

10.2.1 策略模式(Strategy)的定義 122

10.2.2 策略模式(Strategy)的說明 122

10.2.3 策略模式(Strategy)的實現范例 123

10.3 使用策略模式(Strategy)實現攻擊計算 124

10.3.1 攻擊流程的實現 125

10.3.2 實現說明 125

10.3.3 使用策略模式(Strategy)的優點 132

10.3.4 實現策略模式(Strategy)時的注意事項 133

10.4 策略模式(Strategy)面對變化時 134

10.5 結論 135

第11章 攻擊特效與擊中反應——模板方法模式(Template Method) 137

11.1 武器的攻擊流程 137

11.2 模板方法模式(Template Method) 139

11.2.1 模板方法模式(Template Method)的定義 139

11.2.2 模板方法模式(Template Method)的說明 141

11.2.3 模板方法模式(Template Method)的實現范例 141

11.3 使用模板方法模式實現攻擊與擊中流程 142

11.3.1 攻擊與擊中流程的實現 143

11.3.2 實現說明 143

11.3.3 運用模板方法模式(Template Method)的優點 145

11.3.4 修改擊中流程的實現 145

11.4 模板方法模式(Template Method)面對變化時 147

11.5 結論 149

第12章 角色AI——狀態模式(State) 150

12.1 角色的AI 150

12.2 狀態模式(State) 158

12.3 使用狀態模式(State)實現角色AI 159

12.3.1 角色AI的實現 159

12.3.2 實現說明 160

12.3.3 使用狀態模式(State)的優點 169

12.3.4 角色AI執行流程 169

12.4 狀態模式(State)面對變化時 170

12.5 結論 172

第13章 角色系統 174

13.1 角色類 174

13.2 游戲角色管理系統 176

第4篇 角色的產生

第14章 游戲角色的產生——工廠方法模式(Factory Method) 183

14.1 產生角色 183

14.2 工廠方法模式(Factory Method) 188

14.2.1 工廠方法模式(Factory Method)的定義 188

14.2.2 工廠方法模式(Factory Method)的說明 189

14.2.3 工廠方法模式(Factory Method)的實現范例 189

14.3 使用工廠方法模式(Factory Method)產生角色對象 195

14.3.1 角色工廠類 195

14.3.2 實現說明 196

14.3.3 使用工廠方法模式(Factory Method)的優點 199

14.3.4 工廠方法模式(Factory Method)的實現說明 199

14.4 工廠方法模式(Factory Method)面對變化時 203

14.5 結論 205

第15章 角色的組裝——建造者模式(Builder) 206

15.1 角色功能的組裝 206

15.2 建造者模式(Builder) 213

15.2.1 建造者模式(Builder)的定義 213

15.2.2 建造者模式(Builder)的說明 214

15.2.3 建造者模式(Builder)的實現范例 215

15.3 使用建造者模式(Builder)組裝角色的各項功能 217

15.3.1 角色功能的組裝 218

15.3.2 實現說明 219

15.3.3 使用建造者模式(Builder)的優點 226

15.3.4 角色建造者的執行流程 226

15.4 建造者模式(Builder)面對變化時 227

15.5 結論 228

第16章 游戲屬性管理功能——享元模式(Flyweight) 229

16.1 游戲屬性的管理 229

16.2 享元模式(Flyweight) 236

16.2.1 享元模式(Flyweight)的定義 236

16.2.2 享元模式(Flyweight)的說明 237

16.2.3 享元模式(Flyweight)的實現范例 238

16.3 使用享元模式(Flyweight)實現游戲 242

16.3.1 SceneState的實現 242

16.3.2 實現說明 245

16.3.3 使用享元模式(Flyweight)的優點 250

16.3.4 享元模式(Flyweight)的實現說明 250

16.4 享元模式(Flyweight)面對變化時 252

16.5 結論 252

第5篇 戰爭開始

第17章 Unity3D的界面設計——組合模式(Composite) 254

17.1 玩家界面設計 254

17.2 組合模式(Composite) 259

17.2.1 組合模式(Composite)的定義 259

17.2.2 組合模式(Composite)的說明 260

17.2.3 組合模式(Composite)的實現范例 261

17.2.4 分了兩個子類但是要使用同一個操作界面 264

17.3 Unity3D游戲對象的分層式管理功能 265

17.3.1 游戲對象的分層管理 265

17.3.2 正確有效地獲取UI的游戲對象 266

17.3.3 游戲用戶界面的實現 267

17.3.4 兵營界面的實現 269

17.4 結論 274

第18章 兵營系統及兵營信息顯示 276

18.1 兵營系統 276

18.2 兵營系統的組成 277

18.3 初始兵營系統 281

18.4 兵營信息的顯示流程 287

第19章 兵營訓練單位——命令模式(Command) 288

19.1 兵營界面上的命令 288

19.2 命令模式(Command) 291

19.2.1 命令模式(Command)的定義 291

19.2.2 命令模式(Command)的說明 294

19.2.3 命令模式(Command)的實現范例 294

19.3 使用命令模式(Command)實現兵營訓練角色 297

19.3.1 訓練命令的實現 297

19.3.2 實現說明 298

19.3.3 執行流程 302

19.3.4 實現命令模式(Command)時的注意事項 303

19.4 命令模式(Command)面對變化時 305

19.5 結論 306

第20章 關卡設計——責任鏈模式(Chain of Responsibility) 307

20.1 關卡設計 307

20.2 責任鏈模式(Chain of Responsibility) 312

20.2.1 責任鏈模式(Chain of Responsibility)的定義 312

20.2.2 責任鏈模式(Chain of Responsibility)的說明 314

20.2.3 責任鏈模式(Chain of Responsibility)的實現范例 314

20.3 使用責任鏈模式(Chain of Responsibility)實現關卡系統 317

20.3.1 關卡系統的設計 317

20.3.2 實現說明 318

20.3.3 使用責任鏈模式(Chain of Responsibility)的優點 329

20.3.4 實現責任鏈模式(Chain of Responsibility)時的注意事項 329

20.4 責任鏈模式(Chain of Responsibility)面對變化時 330

20.5 結論 332

第6篇 輔助系統

第21章 成就系統—觀察者模式(Observer) 334

21.1 成就系統 334

21.2 觀察者模式(Observer) 338

21.2.1 觀察者模式(Observer)的定義 338

21.2.2 觀察者模式(Observer)的說明 340

21.2.3 觀察者模式(Observer)的實現范例 341

21.3 使用觀察者模式(Observer)實現成就系統 344

21.3.1 成就系統的新架構 344

21.3.2 實現說明 346

21.3.3 使用觀察者模式(Observer)的優點 358

21.3.4 實現觀察者模式(Observer)時的注意事項 358

21.4 觀察者模式(Observer)面對變化時 359

21.5 結論 361

第22章 存盤功能—備忘錄模式(Memento) 362

22.1 存儲成就記錄 362

22.2 備忘錄模式(Memento) 366

22.2.1 備忘錄模式(Memento)的定義 366

22.2.2 備忘錄模式(Memento)的說明 367

22.2.3 備忘錄模式(Memento)的實現范例 367

22.3 使用備忘錄模式(Memento)實現成就記錄的保存 371

22.3.1 成就記錄保存的功能設計 371

22.3.2 實現說明 371

22.3.3 使用備忘錄模式(Memento)的優點 374

22.3.4 實現備忘錄模式(Memento)的注意事項 374

22.4 備忘錄模式(Memento)面對變化時 374

22.5 結論 375

第23章 角色信息查詢—訪問者模式(Visitor) 376

23.1 角色信息的提供 376

23.2 訪問者模式(Visitor) 385

23.2.1 訪問者模式(Visitor)的定義 386

23.2.2 訪問者模式(Visitor)的說明 390

23.2.3 訪問者模式(Visitor)的實現范例 392

23.3 使用訪問者模式(Visitor)實現角色信息查詢 397

23.3.1 角色信息查詢的實現設計 397

23.3.2 實現說明 398

23.3.3 使用訪問者模式(Visitor)的優點 405

23.3.4 實現訪問者模式(Visitor)時的注意事項 405

23.4 訪問者模式(Visitor)面對變化時 405

23.5 結論 408

第7篇 調整與優化

第24章 前綴字尾—裝飾模式(Decorator) 410

24.1 前綴后綴系統 410

24.2 裝飾模式(Decorator) 415

24.2.1 裝飾模式(Decorator)的定義 415

24.2.2 裝飾模式(Decorator)的說明 418

24.2.3 裝飾模式(Decorator)的實現范例 419

24.3 使用裝飾模式(Decorator)實現前綴后綴的功能 422

24.3.1 前綴后綴功能的架構設計 423

24.3.2 實現說明 423

24.3.3 使用裝飾模式(

在線預覽

第3章游戲場景的轉換——狀態模式(State)

3.1 游戲場景本書使用Unity3D游戲引擎作為開發工具,而Unity3D是使用場景(Scene)作為游戲運行時的環境。開始制作游戲時,開發者會將游戲需要的素材(3D模型、游戲對象)放到一個場景中,然后編寫對應的程序代碼,之后只要單擊Play按鈕,就可以開始運行游戲。除了Unity3D之外,筆者過去開發游戲時使用的游戲引擎(Game Engine)或開發框架(SDK、Framework),多數也都存在“場景”的概念,例如:? 早期Java Phone的J2ME開發SDK中使用的Canvas類;? Android的Java開發SDK中使用的Activity類;? iOS上2D游戲開發工具Cocos2D中使用的CCScene類。雖然各種工具不見得都使用場景(Scene)這個名詞,但在實現上,一樣可使用相同的方式來呈現。而上面所列的各個類,都可以被拿來作為游戲實現中“場景”轉換的目標。3.1.1 場景的轉換當游戲比較復雜時,通常會設計成多個場景,讓玩家在幾個場景之間轉換,某一個場景可能是角色在一個大地圖上行走,而另一個場景則是在地下洞穴探險。這樣的設計方式其實很像是舞臺劇的呈現方式,編劇們設計了一幕幕的場景讓演員們在其間穿梭演出,而每幕之間的差異,可能是在布景擺設或參與演出角色的不同,但對于觀眾來說,同時間只會看到演員們在某一個場景中的演出。要怎樣才能真正應用“場景”來開發游戲呢?讀者可以回想一下,當我們打開游戲App或開始運行游戲軟件時,會遇到什么樣的畫面:出現游戲Logo、播放游戲片頭、加載游戲數據、出現游戲主畫面、等待玩家登錄游戲、進入游戲主畫面,接下來玩家可能是在大地圖上打怪或進入副本刷關卡……。游戲畫面轉換如圖3-1所示。 圖3-1 游戲畫面轉換就以上面的說明為例,我們可規劃出下面數個場景,每個場景分別負責多項功能的執行,如圖3-2所示。 圖3-2 每個場景負責執行的游戲功能? 登錄場景:負責游戲片頭、加載游戲數據、出現游戲主畫面、等待玩家登錄游戲。? 主畫面場景:負責進入游戲畫面、玩家在主城/主畫面中的操作、在地圖上打怪打寶……? 戰斗場景:負責與玩家組隊之后進入副本關卡、挑戰王怪……在游戲場景規劃完成后,就可以利用“狀態圖”將各場景的關系連接起來,并且說明它們之間的轉換條件以及狀態轉換的流程,如圖3-3所示。 圖3-3 各場景轉換條件以及狀態轉換的“狀態圖”即便我們換了一個游戲類型來實現,一樣可以使用相同的場景分類方式,將游戲功能進行歸類,例如:卡牌游戲可按如下分類:? 登錄場景:負責游戲片頭、加載游戲數據、出現游戲主畫面、等待玩家登錄游戲。? 主畫面場景:玩家抽卡片、合成卡牌、查看卡牌……? 戰斗場景:挑戰關卡、卡片對戰……轉珠游戲可按如下分類:? 登錄場景:負責游戲片頭、加載游戲數據、出現游戲主畫面、等待玩家登錄游戲。? 主畫面場景:查看關卡進度、關卡信息、商城、抽轉珠……? 戰斗場景:挑戰關卡、轉珠對戰……當然,如果是更復雜的單機版游戲或大型多人在線游戲(MMORPG),還可以再細分出多個場景來負責對應的游戲功能。切分場景的好處將游戲中不同的功能分類在不同的場景中來執行,除了可以將游戲功能執行時需要的環境明確分類之外,“重復使用”也是使用場景轉換的好處之一。從上面幾個例子中可以看出,“登錄場景”幾乎是每款游戲必備的場景之一。而一般在登錄場景中,會實現游戲初始化功能或玩家登錄游戲時需要執行的功能,例如:? 單機游戲:登錄場景可以有加載游戲數據、讓玩家選擇存盤、進入游戲等步驟。? 在線游戲:登錄場景包含了許多復雜的在線登錄流程,比如使用第三方認證系統、使用玩家自定義賬號、與服務器連接、數據驗證……對于大多數的游戲開發公司來說,登錄場景實現的功能,會希望通用于不同的游戲開發項目,使其保持流程的一致性。尤其對于在線游戲這種類型的項目而言,由于登錄流程較為復雜,若能將各項目共同的部分(場景)獨立出來,由專人負責開發維護并同步更新給各個項目,那么效率就能獲得提升,也是比較安全的方式。在項目開發時,若是能重復使用這些已經設計良好的場景,將會減少許多開發時間。更多的優點將在后續章節中說明。本書范例場景的規劃在本書范例中,《P級陣地》規劃了3個場景,如圖3-4所示。 圖3-4 《P級陣地》規劃的3個場景? 開始場景(StarScene):GameLoop游戲對象(GameObject)的所在,游戲啟動及相關游戲設置的加載。? 主畫面場景(MainMenuScene):顯示游戲名稱和“開始”按鈕。? 戰斗場景(BattleScene):游戲主要執行的場景。3.1.2 游戲場景可能的實現方式實現Unity3D的場景轉換較為直接的方式如下:Listing 3-1 一般場景控制的寫法public class SceneManager{ private string m_state = "開始"; // 改換場景 public void ChangeScene(string StateName) { m_state = StateName;

switch(m_state) { case "菜單": Application.LoadLevel(“MainMenuScene”); break; case "主場景": Application.LoadLevel(“GameScene”); break; } } // 更新 public void Update() { switch(m_state) { case "開始": //... break; case "菜單": //... break; case "主場景": //... break; } }}

上述的實現方式會有以下缺點:只要增加一個狀態,則所有switch(m_state)的程序代碼都需要增加對應的程序代碼。與每一個狀態有關的對象,都必須在SceneManager類中被保留,當這些對象被多個狀態共享時,可能會產生混淆,不太容易識別是由哪個狀態設置的,造成游戲程序調試上的困難。每一個狀態可能使用不同的類對象,容易造成SceneManager類過度依賴其他類,讓SceneManager類不容易移植到其他項目中。為了避免出現上述缺點,修正的目標會希望使用一個“場景類”來負責維護一個場景,讓與此場景相關的程序代碼和對象能整合在一起。這個負責維護的“場景類”,其主要工作如下:? 場景初始化;? 場景結束后,負責清除資源;? 定時更新游戲邏輯單元;? 轉換到其他場景;? 其他與該場景有關的游戲實現。由于在范例程序中我們規劃了3個場景,所以會產生對應的3個“場景類”,但如何讓這3個“場景類”相互合作、彼此轉換呢?我們可以使用GoF的狀態模式(State)來解決這些問題。3.2 狀態模式(State)狀態模式(State),在多數的設計模式書籍中都會提及,它也是游戲程序設計中應用最頻繁的一種模式。主要是因為“狀態”經常被應用在游戲設計的許多環節中,包含AI人工智能狀態、賬號登錄狀態、角色狀態……3.2.1 狀態模式(State)的定義狀態模式(State),在GoF中的解釋是:“讓一個對象的行為隨著內部狀態的改變而變化,而該對象也像是換了類一樣”。如果將GoF對狀態模式(State)的定義改以游戲的方式來解釋,就會像下面這樣:“當德魯伊(對象)由人形變化為獸形狀態(內部狀態改變)時,他所施展的技能(對象的行為)也會有所變化,玩家此時就像是在操作另一個不同的角色(像是換了類)”。“德魯伊“是一種經常出現在角色扮演游戲(RPG)中的角色名稱。變化外形是他們常使用的能力,通過外形的變化,使德魯伊具備了轉換為其他形體的能力,而變化為“獸形”是比較常見的游戲設計。當玩家決定施展外形轉換能力時,德魯伊會進入“獸形狀態”,這時候的德魯伊會以“獸形”來表現其行為,包含移動和攻擊施展的方式;當玩家決定轉換回人形時,德魯伊會復原為一般形態,繼續與游戲世界互動。所以,變化外形的能力可以看成是德魯伊的一種“內部狀態的轉換”。通過變化外形的結果,角色表現出另外一種行為模式,而這一切的轉化過程都可以由德魯伊的內部控制功能來完成,玩家不必理解這個轉化過程。但無論怎么變化,玩家操作的角色都是德魯伊,并不會因為他內部狀態的轉變而有所差異。當某個對象狀態改變時,雖然它“表現的行為”會有所變化,但是對于客戶端來說,并不會因為這樣的變化,而改變對它的“操作方法”或“信息溝通”的方式。也就是說,這個對象與外界的對應方式不會有任何改變。但是,對象的內部確實是會通過“更換狀態類對象”的方式來進行狀態的轉換。當狀態對象更換到另一個類時,對象就會通過新的狀態類,表現出它在這個狀態下該有的行為。但這一切只會發生在對象內部,對客戶端來說,不需要了解這些狀態轉換的過程及對應的方式。3.2.2 狀態模式(State)的說明狀態模式(State)的結構如圖3-5所示。 圖3-5 狀態模式的結構圖參與者的說明如下:? Context(狀態擁有者)? 是一個具有“狀態”屬性的類,可以制定相關的接口,讓外界能夠得知狀態的改變或通過操作讓狀態改變。? 有狀態屬性的類,例如:游戲角色有潛行、攻擊、施法等狀態;好友上線、脫機、忙碌等狀態;GoF使用TCP聯網為例,有已連接、等待連接、斷線等狀態。這些類中會有一個ConcreteState[X]子類的對象為其成員,用來代表當前的狀態。? State(狀態接口類):制定狀態的接口,負責規范Context(狀態擁有者)在特定狀態下要表現的行為。? ConcreteState(具體狀態類)? 繼承自State(狀態接口類)。? 實現Context(狀態擁有者)在特定狀態下該有的行為。例如,實現角色在潛行狀態時該有的行動變緩、3D模型變半透明、不能被敵方角色察覺等行為。3.2.3 狀態模式(State)的實現范例首先定義Context類:Listing 3-2 定義Context類(State.cs)public class Context{ State m_State = null;

public void Request(int Value) { m_State.Handle(Value); }

public void SetState(State theState ) { Debug.Log ("Context.SetState:" theState); m_State = theState; }}Context類中,擁有一個State屬性用來代表當前的狀態,外界可以通過Request方法,讓Context類呈現當前狀態下的行為。SetState方法可以指定Context類當前的狀態,而State狀態接口類則用來定義每一個狀態該有的行為:Listing 3-3 State類(State.cs)public abstract class State{ protected Context m_Context = null; public State(Context theContext) { m_Context = theContext; } public abstract void Handle(int Value);}在產生State類對象時,可以傳入Context類對象,并將其指定給State的類成員m_Context,讓State類在后續的操作中,可以獲取Context對象的信息或操作Context對象。然后定義Handle抽象方法,讓繼承的子類可以重新定義該方法,來呈現各自不同的狀態行為。定義3個繼承自State類的子類:Listing 3-4 定義3個狀態(State.cs)// 狀態Apublic class ConcreteStateA : State{ public ConcreteStateA(Context theContext):base(theContext) {}

public override void Handle (int Value) { Debug.Log ("ConcreteStateA.Handle"); if( Value > 10) m_Context.SetState( new ConcreteStateB(m_Context)); }}

// 狀態Bpublic class ConcreteStateB : State{ public ConcreteStateB(Context theContext):base(theContext) {}

public override void Handle (int Value) { Debug.Log ("ConcreteStateB.Handle"); if( Value > 20) m_Context.SetState( new ConcreteStateC(m_Context)); } }

// 狀態Cpublic class ConcreteStateC : State{ public ConcreteStateC(Context theContext):base(theContext) {} public override void Handle (int Value) { Debug.Log ("ConcreteStateC.Handle"); if( Value > 30) m_Context.SetState( new ConcreteStateA(m_Context)); } }上述3個子類,都要重新定義父類State的Handle抽象方法,用來表示在各自狀態下的行為。在范例中,我們先讓它們各自顯示不同的信息(代表當前的狀態行為),再按照本身狀態的行為定義來判斷是否要通知Context對象轉換到另一個狀態。Context類中提供了一個SetState方法,讓外界能夠設置Context對象當前的狀態,而所謂的“外界”,也可以是由另一個State狀態來調用。所以實現上,狀態的轉換可以有下列兩種方式:? 交由Context類本身,按條件在各狀態之間轉換;? 產生Context類對象時,馬上指定初始狀態給Context對象,而在后續執行過程中的狀態轉換則交由State對象負責,Context對象不再介入。筆者在實現時,大部分情況下會選擇第2種方式,原因在于:狀態對象本身比較清楚“在什么條件下,可以讓Context對象轉移到另一個State狀態”。所以在每個ConcreteState類的程序代碼中,可以看到“狀態轉換條件”的判斷,以及設置哪一個ConcreteState對象成為新的狀態。每個ConcreteState狀態都可以保持自己的屬性值,作為狀態轉換或展現狀態行為的依據,不會與其他的ConcreteState狀態混用,在維護時比較容易理解。因為判斷條件及狀態屬性都被轉換到ConcreteState類中,故而可縮減Context類的大小。4個類定義好之后,我們可以通過測試范例來看看客戶端程序會怎樣利用這個設計:Listing 3-5 State的測試范例(StateTest.cs) void UnitTest() { Context theContext = new Context(); theContext.SetState( new ConcreteStatA(theContext ));

theContext.Request( 5 ); theContext.Request( 15 ); theContext.Request( 25 ); theContext.Request( 35 ); }首先產生Context對象theContext,并立即設置為ConcreteStateA狀態;然后調用Context類的Request方法,并傳入作為“狀態轉換判斷”用途的參數,讓當前狀態(ConcreteStateA)判斷是否要轉移到ConcreteStateB;調用幾次Request方法,并傳入不同的參數。從輸出的信息中可以看到,Context對象的狀態由ConcreteStateA按序轉換到ConcreteStateB、 ConcreteStateC狀態,回到ConcreteStateA狀態。 State測試范例產生的信息 Context.SetState:DesignPattern_State.ConcreteStateA ConcreteStateA.Handle ConcreteStateA.Handle Context.SetState:DesignPattern_State.ConcreteStateB Context.SetState:DesignPattern_State.ConcreteStateC Context.SetState:DesignPattern_State.ConcreteStateA3.3 使用狀態模式(State)實現游戲場景的轉換在Unity3D的環境中,游戲只會在一個場景中運行,所以我們可以讓每個場景都由一個“場景類”來負責維護。此時,如果將場景類當成“狀態”來比喻的話,那么就可以利用狀態模式(State)的轉換原理,來完成場景轉換的功能。由于每個場景所負責執行的功能不同,通過狀態模式(State)的狀態轉移,除了可以實現游戲內部功能的轉換外,對于客戶端來說,也不必根據不同的游戲狀態來編寫不同的程代碼,同時也減少了外界對于不同游戲狀態的依賴性。而原本的Unity3D場景轉換判斷功能,可以在各自的場景類中完成,并且狀態模式(State)同時間也只會讓一個狀態存在(同時間只會有一個狀態在運行),因此可以滿足Unity3D執行時只能有一個場景(狀態)存在的要求。3.3.1 SceneState的實現《P級陣地》的場景分成3個:開始場景(StarScene)、主畫面場景(MainM

網友評論(不代表本站觀點)

免責聲明

更多出版社
主站蜘蛛池模板: 晋中市| 卫辉市| 芦山县| 抚松县| 马龙县| 桦甸市| 济南市| 芮城县| 霍邱县| 武威市| 会泽县| 余姚市| 子长县| 和林格尔县| 柞水县| 郁南县| 冀州市| 扎兰屯市| 阳城县| 博野县| 四子王旗| 灵璧县| 岳西县| 诸暨市| 定远县| 威海市| 巴东县| 雅江县| 阜宁县| 麻江县| 宝山区| 兰西县| 莱西市| 景泰县| 上杭县| 谷城县| 利辛县| 莱州市| 六安市| 宁阳县| 兴仁县|