《設(shè)計(jì)模式與游戲開(kāi)發(fā)》是作者“十年磨一劍”,將設(shè)計(jì)模式理論巧妙地融合到實(shí)踐中的教材。 全書采用了整合式的項(xiàng)目教學(xué),即以一個(gè)游戲的范例來(lái)應(yīng)用23種設(shè)計(jì)模式的實(shí)現(xiàn)貫穿全書,讓讀者學(xué)習(xí)到整個(gè)游戲開(kāi)發(fā)的全過(guò)程和作者想要傳承的經(jīng)驗(yàn),并以淺顯易懂的比喻來(lái)解析難以理解的設(shè)計(jì)模式,讓想深入了解此領(lǐng)域的讀者更加容易上手。 本書既可以作為大學(xué)、專科和職業(yè)院校游戲程序設(shè)計(jì)專業(yè)的教材,也可以作為游戲從業(yè)人員提高游戲設(shè)計(jì)能力和規(guī)范運(yùn)用設(shè)計(jì)模式的培訓(xùn)教材,還可以作為有這方面職業(yè)興趣的讀者學(xué)習(xí)和提高的自學(xué)參考書。
十年磨一劍,作者將設(shè)計(jì)模式理論巧妙地融入到實(shí)踐中,以一個(gè)游戲的完整實(shí)現(xiàn)呈現(xiàn)設(shè)計(jì)模式的應(yīng)用及經(jīng)驗(yàn)的傳承 《軒轅劍》之父——蔡明宏、博學(xué)游戲制作人——李佳澤、Product Evangelist at Unity Technologies——Kelvin Lo、信仁軟件設(shè)計(jì)創(chuàng)辦人—— 賴信仁、博學(xué)3D游戲美術(shù)——劉明愷 聯(lián)合推薦全書采用了整合式的項(xiàng)目教學(xué),即以一個(gè)游戲的范例來(lái)應(yīng)用23種設(shè)計(jì)模式的實(shí)現(xiàn)貫穿全書,讓讀者學(xué)習(xí)到整個(gè)游戲開(kāi)發(fā)的全過(guò)程和作者想要傳承的經(jīng)驗(yàn),并以淺顯易懂的比喻來(lái)解析難以理解的設(shè)計(jì)模式,讓想深入了解此領(lǐng)域的讀者更加容易上手。
蔡升達(dá)當(dāng)年為實(shí)現(xiàn)游戲夢(mèng)從學(xué)術(shù)界進(jìn)入游戲業(yè),累積了10年游戲開(kāi)發(fā)經(jīng)驗(yàn),包含多款大型多人線上游戲(MMORPG)、網(wǎng)頁(yè)游戲(Web Game)、移動(dòng)平臺(tái)連線游戲(APP Game)。曾任職于臺(tái)灣地區(qū)知名游戲開(kāi)發(fā)公司,擔(dān)任游戲設(shè)計(jì)師、專案程序統(tǒng)籌、研發(fā)技術(shù)中心經(jīng)理等職務(wù),現(xiàn)任知名新創(chuàng)團(tuán)隊(duì)研發(fā)總監(jiān)一職。擅長(zhǎng)游戲程序設(shè)計(jì)、網(wǎng)絡(luò)程序設(shè)計(jì)、分布式系統(tǒng)設(shè)計(jì)、電腦圖學(xué)、影像搜索、游戲制作規(guī)劃及運(yùn)作、游戲?qū)0腹芾怼O矚g閱讀,家中有上千本藏書,包含信息技術(shù)、文學(xué)、奇幻小說(shuō)、歷史小說(shuō)等,因?yàn)榭戳撕芏啵砸灿泻芏嘞敕ㄏ肱c人分享。構(gòu)想多年之后,某日下午終于下筆開(kāi)始了這本書。十年磨一劍,作者將設(shè)計(jì)模式理論巧妙地融入到實(shí)踐中,以一個(gè)游戲的完整實(shí)現(xiàn)呈現(xiàn)設(shè)計(jì)模式的應(yīng)用及經(jīng)驗(yàn)的傳承
第1篇 設(shè)計(jì)模式與游戲設(shè)計(jì)
第1章 游戲?qū)崿F(xiàn)中的設(shè)計(jì)模式 2
1.1 設(shè)計(jì)模式的起源 2
1.2 軟件的設(shè)計(jì)模式是什么? 3
1.3 面向?qū)ο笤O(shè)計(jì)中常見(jiàn)的設(shè)計(jì)原則 4
1.4 為什么要學(xué)習(xí)設(shè)計(jì)模式 7
1.5 游戲程序設(shè)計(jì)與設(shè)計(jì)模式 8
1.6 模式的應(yīng)用與學(xué)習(xí)方式 10
1.7 結(jié)論 11
第2章 游戲范例說(shuō)明 12
2.1 游戲范例 12
2.2 GoF的設(shè)計(jì)模式范例 15
第2篇 基礎(chǔ)系統(tǒng)
第3章 游戲場(chǎng)景的轉(zhuǎn)換——狀態(tài)模式(State) 20
3.1 游戲場(chǎng)景 20
3.1.1 場(chǎng)景的轉(zhuǎn)換 20
3.1.2 游戲場(chǎng)景可能的實(shí)現(xiàn)方式 23
3.2 狀態(tài)模式(State) 24
3.2.1 狀態(tài)模式(State)的定義 24
3.2.2 狀態(tài)模式(State)的說(shuō)明 25
3.2.3 狀態(tài)模式(State)的實(shí)現(xiàn)范例 25
3.3 使用狀態(tài)模式(State)實(shí)現(xiàn)游戲場(chǎng)景的轉(zhuǎn)換 28
3.3.1 SceneState的實(shí)現(xiàn) 28
3.3.2 實(shí)現(xiàn)說(shuō)明 29
3.3.3 使用狀態(tài)模式(State)的優(yōu)點(diǎn) 35
3.3.4 游戲執(zhí)行流程及場(chǎng)景轉(zhuǎn)換說(shuō)明 36
3.4 狀態(tài)模式(State)面對(duì)變化時(shí) 37
3.5 結(jié)論 37
第4章 游戲主要類——外觀模式(Facade) 39
4.1 游戲子功能的整合 39
4.2 外觀模式(Facade) 41
4.2.1 外觀模式(Facade)的定義 41
4.2.2 外觀模式(Facade)的說(shuō)明 42
4.2.3 外觀模式(Facade)的實(shí)現(xiàn)說(shuō)明 43
4.3 使用外觀模式(Facade)實(shí)現(xiàn)游戲主程序 44
4.3.1 游戲主程序架構(gòu)設(shè)計(jì) 44
4.3.2 實(shí)現(xiàn)說(shuō)明 45
4.3.3 使用外觀模式(Facade)的優(yōu)點(diǎn) 47
4.3.4 實(shí)現(xiàn)外觀模式(Facade)時(shí)的注意事項(xiàng) 48
4.4 外觀模式(Facade)面對(duì)變化時(shí) 48
4.5 結(jié)論 48
第5章 獲取游戲服務(wù)的對(duì)象——單例模式(Singleton) 50
5.1 游戲?qū)崿F(xiàn)中的對(duì)象 50
5.2 單例模式(Singleton) 51
5.2.1 單例模式(Singleton)的定義 51
5.2.2 單例模式(Singleton)的說(shuō)明 51
5.2.3 單例模式(Singleton)的實(shí)現(xiàn)范例 52
5.3 使用單例模式(Singleton)獲取的游戲服務(wù)對(duì)象 53
5.3.1 游戲服務(wù)類的單例模式實(shí)現(xiàn) 53
5.3.2 實(shí)現(xiàn)說(shuō)明 54
5.3.3 使用單例模式(Singleton)后的比較 55
5.3.4 反對(duì)使用單例模式(Singleton)的原因 55
5.4 少用單例模式(Singleton)時(shí)如何方便地引用到單一對(duì)象 58
5.5 結(jié)論 63
第6章 游戲內(nèi)各系統(tǒng)的整合——中介者模式(Mediator) 64
6.1 游戲系統(tǒng)之間的溝通 64
6.2 中介者模式(Mediator) 68
6.2.1 中介者模式(Mediator)的定義 69
6.2.2 中介者模式(Mediator)的說(shuō)明 69
6.2.3 中介者模式(Mediator)的實(shí)現(xiàn)范例 69
6.3 中介者模式(Mediator)作為系統(tǒng)之間的溝通接口 72
6.3.1 使用中介者模式(Mediator)的系統(tǒng)架構(gòu) 73
6.3.2 實(shí)現(xiàn)說(shuō)明 73
6.3.3 使用中介者模式(Mediator)的優(yōu)點(diǎn) 79
6.3.4 實(shí)現(xiàn)中介者模式(Mediator)時(shí)的注意事項(xiàng) 79
6.4 中介者模式(Mediator)面對(duì)變化時(shí) 80
6.5 結(jié)論 80
第7章 游戲的主循環(huán)——Game Loop 82
7.1 GameLoop由此開(kāi)始 82
7.2 怎么實(shí)現(xiàn)游戲循環(huán)(Game Loop) 84
7.3 在Unity3D中實(shí)現(xiàn)游戲循環(huán) 85
7.4 P級(jí)陣地的游戲循環(huán) 89
7.5 結(jié)論 92
第3篇 角色的設(shè)計(jì)
第8章 角色系統(tǒng)的設(shè)計(jì)分析 94
8.1 游戲角色的架構(gòu) 94
8.2 角色類的規(guī)劃 95
第9章 角色與武器的實(shí)現(xiàn)——橋接模式(Bridge) 98
9.1 角色與武器的關(guān)系 98
9.2 橋接模式(Bridge) 103
9.2.1 橋接模式(Bridge)的定義 103
9.2.2 橋接模式(Bridge)的說(shuō)明 107
9.2.3 橋接模式(Bridge)的實(shí)現(xiàn)范例 108
9.3 使用橋接模式(Bridge)實(shí)現(xiàn)角色與武器接口 110
9.3.1 角色與武器接口設(shè)計(jì) 110
9.3.2 實(shí)現(xiàn)說(shuō)明 111
9.3.3 使用橋接模式(Bridge)的優(yōu)點(diǎn) 116
9.3.4 實(shí)現(xiàn)橋接模式(Bridge)的注意事項(xiàng) 116
9.4 橋接模式(Bridge)面對(duì)變化時(shí) 116
9.5 結(jié)論 117
第10章 角色屬性的計(jì)算——策略模式(Strategy) 118
10.1 角色屬性的計(jì)算需求 118
10.2 策略模式(Strategy) 121
10.2.1 策略模式(Strategy)的定義 122
10.2.2 策略模式(Strategy)的說(shuō)明 122
10.2.3 策略模式(Strategy)的實(shí)現(xiàn)范例 123
10.3 使用策略模式(Strategy)實(shí)現(xiàn)攻擊計(jì)算 124
10.3.1 攻擊流程的實(shí)現(xiàn) 125
10.3.2 實(shí)現(xiàn)說(shuō)明 125
10.3.3 使用策略模式(Strategy)的優(yōu)點(diǎn) 132
10.3.4 實(shí)現(xiàn)策略模式(Strategy)時(shí)的注意事項(xiàng) 133
10.4 策略模式(Strategy)面對(duì)變化時(shí) 134
10.5 結(jié)論 135
第11章 攻擊特效與擊中反應(yīng)——模板方法模式(Template Method) 137
11.1 武器的攻擊流程 137
11.2 模板方法模式(Template Method) 139
11.2.1 模板方法模式(Template Method)的定義 139
11.2.2 模板方法模式(Template Method)的說(shuō)明 141
11.2.3 模板方法模式(Template Method)的實(shí)現(xiàn)范例 141
11.3 使用模板方法模式實(shí)現(xiàn)攻擊與擊中流程 142
11.3.1 攻擊與擊中流程的實(shí)現(xiàn) 143
11.3.2 實(shí)現(xiàn)說(shuō)明 143
11.3.3 運(yùn)用模板方法模式(Template Method)的優(yōu)點(diǎn) 145
11.3.4 修改擊中流程的實(shí)現(xiàn) 145
11.4 模板方法模式(Template Method)面對(duì)變化時(shí) 147
11.5 結(jié)論 149
第12章 角色AI——狀態(tài)模式(State) 150
12.1 角色的AI 150
12.2 狀態(tài)模式(State) 158
12.3 使用狀態(tài)模式(State)實(shí)現(xiàn)角色AI 159
12.3.1 角色AI的實(shí)現(xiàn) 159
12.3.2 實(shí)現(xiàn)說(shuō)明 160
12.3.3 使用狀態(tài)模式(State)的優(yōu)點(diǎn) 169
12.3.4 角色AI執(zhí)行流程 169
12.4 狀態(tài)模式(State)面對(duì)變化時(shí) 170
12.5 結(jié)論 172
第13章 角色系統(tǒng) 174
13.1 角色類 174
13.2 游戲角色管理系統(tǒng) 176
第4篇 角色的產(chǎn)生
第14章 游戲角色的產(chǎn)生——工廠方法模式(Factory Method) 183
14.1 產(chǎn)生角色 183
14.2 工廠方法模式(Factory Method) 188
14.2.1 工廠方法模式(Factory Method)的定義 188
14.2.2 工廠方法模式(Factory Method)的說(shuō)明 189
14.2.3 工廠方法模式(Factory Method)的實(shí)現(xiàn)范例 189
14.3 使用工廠方法模式(Factory Method)產(chǎn)生角色對(duì)象 195
14.3.1 角色工廠類 195
14.3.2 實(shí)現(xiàn)說(shuō)明 196
14.3.3 使用工廠方法模式(Factory Method)的優(yōu)點(diǎn) 199
14.3.4 工廠方法模式(Factory Method)的實(shí)現(xiàn)說(shuō)明 199
14.4 工廠方法模式(Factory Method)面對(duì)變化時(shí) 203
14.5 結(jié)論 205
第15章 角色的組裝——建造者模式(Builder) 206
15.1 角色功能的組裝 206
15.2 建造者模式(Builder) 213
15.2.1 建造者模式(Builder)的定義 213
15.2.2 建造者模式(Builder)的說(shuō)明 214
15.2.3 建造者模式(Builder)的實(shí)現(xiàn)范例 215
15.3 使用建造者模式(Builder)組裝角色的各項(xiàng)功能 217
15.3.1 角色功能的組裝 218
15.3.2 實(shí)現(xiàn)說(shuō)明 219
15.3.3 使用建造者模式(Builder)的優(yōu)點(diǎn) 226
15.3.4 角色建造者的執(zhí)行流程 226
15.4 建造者模式(Builder)面對(duì)變化時(shí) 227
15.5 結(jié)論 228
第16章 游戲?qū)傩怨芾砉δ?mdash;—享元模式(Flyweight) 229
16.1 游戲?qū)傩缘墓芾?229
16.2 享元模式(Flyweight) 236
16.2.1 享元模式(Flyweight)的定義 236
16.2.2 享元模式(Flyweight)的說(shuō)明 237
16.2.3 享元模式(Flyweight)的實(shí)現(xiàn)范例 238
16.3 使用享元模式(Flyweight)實(shí)現(xiàn)游戲 242
16.3.1 SceneState的實(shí)現(xiàn) 242
16.3.2 實(shí)現(xiàn)說(shuō)明 245
16.3.3 使用享元模式(Flyweight)的優(yōu)點(diǎn) 250
16.3.4 享元模式(Flyweight)的實(shí)現(xiàn)說(shuō)明 250
16.4 享元模式(Flyweight)面對(duì)變化時(shí) 252
16.5 結(jié)論 252
第5篇 戰(zhàn)爭(zhēng)開(kāi)始
第17章 Unity3D的界面設(shè)計(jì)——組合模式(Composite) 254
17.1 玩家界面設(shè)計(jì) 254
17.2 組合模式(Composite) 259
17.2.1 組合模式(Composite)的定義 259
17.2.2 組合模式(Composite)的說(shuō)明 260
17.2.3 組合模式(Composite)的實(shí)現(xiàn)范例 261
17.2.4 分了兩個(gè)子類但是要使用同一個(gè)操作界面 264
17.3 Unity3D游戲?qū)ο蟮姆謱邮焦芾砉δ?265
17.3.1 游戲?qū)ο蟮姆謱庸芾?265
17.3.2 正確有效地獲取UI的游戲?qū)ο?266
17.3.3 游戲用戶界面的實(shí)現(xiàn) 267
17.3.4 兵營(yíng)界面的實(shí)現(xiàn) 269
17.4 結(jié)論 274
第18章 兵營(yíng)系統(tǒng)及兵營(yíng)信息顯示 276
18.1 兵營(yíng)系統(tǒng) 276
18.2 兵營(yíng)系統(tǒng)的組成 277
18.3 初始兵營(yíng)系統(tǒng) 281
18.4 兵營(yíng)信息的顯示流程 287
第19章 兵營(yíng)訓(xùn)練單位——命令模式(Command) 288
19.1 兵營(yíng)界面上的命令 288
19.2 命令模式(Command) 291
19.2.1 命令模式(Command)的定義 291
19.2.2 命令模式(Command)的說(shuō)明 294
19.2.3 命令模式(Command)的實(shí)現(xiàn)范例 294
19.3 使用命令模式(Command)實(shí)現(xiàn)兵營(yíng)訓(xùn)練角色 297
19.3.1 訓(xùn)練命令的實(shí)現(xiàn) 297
19.3.2 實(shí)現(xiàn)說(shuō)明 298
19.3.3 執(zhí)行流程 302
19.3.4 實(shí)現(xiàn)命令模式(Command)時(shí)的注意事項(xiàng) 303
19.4 命令模式(Command)面對(duì)變化時(shí) 305
19.5 結(jié)論 306
第20章 關(guān)卡設(shè)計(jì)——責(zé)任鏈模式(Chain of Responsibility) 307
20.1 關(guān)卡設(shè)計(jì) 307
20.2 責(zé)任鏈模式(Chain of Responsibility) 312
20.2.1 責(zé)任鏈模式(Chain of Responsibility)的定義 312
20.2.2 責(zé)任鏈模式(Chain of Responsibility)的說(shuō)明 314
20.2.3 責(zé)任鏈模式(Chain of Responsibility)的實(shí)現(xiàn)范例 314
20.3 使用責(zé)任鏈模式(Chain of Responsibility)實(shí)現(xiàn)關(guān)卡系統(tǒng) 317
20.3.1 關(guān)卡系統(tǒng)的設(shè)計(jì) 317
20.3.2 實(shí)現(xiàn)說(shuō)明 318
20.3.3 使用責(zé)任鏈模式(Chain of Responsibility)的優(yōu)點(diǎn) 329
20.3.4 實(shí)現(xiàn)責(zé)任鏈模式(Chain of Responsibility)時(shí)的注意事項(xiàng) 329
20.4 責(zé)任鏈模式(Chain of Responsibility)面對(duì)變化時(shí) 330
20.5 結(jié)論 332
第6篇 輔助系統(tǒng)
第21章 成就系統(tǒng)—觀察者模式(Observer) 334
21.1 成就系統(tǒng) 334
21.2 觀察者模式(Observer) 338
21.2.1 觀察者模式(Observer)的定義 338
21.2.2 觀察者模式(Observer)的說(shuō)明 340
21.2.3 觀察者模式(Observer)的實(shí)現(xiàn)范例 341
21.3 使用觀察者模式(Observer)實(shí)現(xiàn)成就系統(tǒng) 344
21.3.1 成就系統(tǒng)的新架構(gòu) 344
21.3.2 實(shí)現(xiàn)說(shuō)明 346
21.3.3 使用觀察者模式(Observer)的優(yōu)點(diǎn) 358
21.3.4 實(shí)現(xiàn)觀察者模式(Observer)時(shí)的注意事項(xiàng) 358
21.4 觀察者模式(Observer)面對(duì)變化時(shí) 359
21.5 結(jié)論 361
第22章 存盤功能—備忘錄模式(Memento) 362
22.1 存儲(chǔ)成就記錄 362
22.2 備忘錄模式(Memento) 366
22.2.1 備忘錄模式(Memento)的定義 366
22.2.2 備忘錄模式(Memento)的說(shuō)明 367
22.2.3 備忘錄模式(Memento)的實(shí)現(xiàn)范例 367
22.3 使用備忘錄模式(Memento)實(shí)現(xiàn)成就記錄的保存 371
22.3.1 成就記錄保存的功能設(shè)計(jì) 371
22.3.2 實(shí)現(xiàn)說(shuō)明 371
22.3.3 使用備忘錄模式(Memento)的優(yōu)點(diǎn) 374
22.3.4 實(shí)現(xiàn)備忘錄模式(Memento)的注意事項(xiàng) 374
22.4 備忘錄模式(Memento)面對(duì)變化時(shí) 374
22.5 結(jié)論 375
第23章 角色信息查詢—訪問(wèn)者模式(Visitor) 376
23.1 角色信息的提供 376
23.2 訪問(wèn)者模式(Visitor) 385
23.2.1 訪問(wèn)者模式(Visitor)的定義 386
23.2.2 訪問(wèn)者模式(Visitor)的說(shuō)明 390
23.2.3 訪問(wèn)者模式(Visitor)的實(shí)現(xiàn)范例 392
23.3 使用訪問(wèn)者模式(Visitor)實(shí)現(xiàn)角色信息查詢 397
23.3.1 角色信息查詢的實(shí)現(xiàn)設(shè)計(jì) 397
23.3.2 實(shí)現(xiàn)說(shuō)明 398
23.3.3 使用訪問(wèn)者模式(Visitor)的優(yōu)點(diǎn) 405
23.3.4 實(shí)現(xiàn)訪問(wèn)者模式(Visitor)時(shí)的注意事項(xiàng) 405
23.4 訪問(wèn)者模式(Visitor)面對(duì)變化時(shí) 405
23.5 結(jié)論 408
第7篇 調(diào)整與優(yōu)化
第24章 前綴字尾—裝飾模式(Decorator) 410
24.1 前綴后綴系統(tǒng) 410
24.2 裝飾模式(Decorator) 415
24.2.1 裝飾模式(Decorator)的定義 415
24.2.2 裝飾模式(Decorator)的說(shuō)明 418
24.2.3 裝飾模式(Decorator)的實(shí)現(xiàn)范例 419
24.3 使用裝飾模式(Decorator)實(shí)現(xiàn)前綴后綴的功能 422
24.3.1 前綴后綴功能的架構(gòu)設(shè)計(jì) 423
24.3.2 實(shí)現(xiàn)說(shuō)明 423
24.3.3 使用裝飾模式(
第3章游戲場(chǎng)景的轉(zhuǎn)換——狀態(tài)模式(State)
3.1 游戲場(chǎng)景本書使用Unity3D游戲引擎作為開(kāi)發(fā)工具,而Unity3D是使用場(chǎng)景(Scene)作為游戲運(yùn)行時(shí)的環(huán)境。開(kāi)始制作游戲時(shí),開(kāi)發(fā)者會(huì)將游戲需要的素材(3D模型、游戲?qū)ο?放到一個(gè)場(chǎng)景中,然后編寫對(duì)應(yīng)的程序代碼,之后只要單擊Play按鈕,就可以開(kāi)始運(yùn)行游戲。除了Unity3D之外,筆者過(guò)去開(kāi)發(fā)游戲時(shí)使用的游戲引擎(Game Engine)或開(kāi)發(fā)框架(SDK、Framework),多數(shù)也都存在“場(chǎng)景”的概念,例如:? 早期Java Phone的J2ME開(kāi)發(fā)SDK中使用的Canvas類;? Android的Java開(kāi)發(fā)SDK中使用的Activity類;? iOS上2D游戲開(kāi)發(fā)工具Cocos2D中使用的CCScene類。雖然各種工具不見(jiàn)得都使用場(chǎng)景(Scene)這個(gè)名詞,但在實(shí)現(xiàn)上,一樣可使用相同的方式來(lái)呈現(xiàn)。而上面所列的各個(gè)類,都可以被拿來(lái)作為游戲?qū)崿F(xiàn)中“場(chǎng)景”轉(zhuǎn)換的目標(biāo)。3.1.1 場(chǎng)景的轉(zhuǎn)換當(dāng)游戲比較復(fù)雜時(shí),通常會(huì)設(shè)計(jì)成多個(gè)場(chǎng)景,讓玩家在幾個(gè)場(chǎng)景之間轉(zhuǎn)換,某一個(gè)場(chǎng)景可能是角色在一個(gè)大地圖上行走,而另一個(gè)場(chǎng)景則是在地下洞穴探險(xiǎn)。這樣的設(shè)計(jì)方式其實(shí)很像是舞臺(tái)劇的呈現(xiàn)方式,編劇們?cè)O(shè)計(jì)了一幕幕的場(chǎng)景讓演員們?cè)谄溟g穿梭演出,而每幕之間的差異,可能是在布景擺設(shè)或參與演出角色的不同,但對(duì)于觀眾來(lái)說(shuō),同時(shí)間只會(huì)看到演員們?cè)谀骋粋€(gè)場(chǎng)景中的演出。要怎樣才能真正應(yīng)用“場(chǎng)景”來(lái)開(kāi)發(fā)游戲呢?讀者可以回想一下,當(dāng)我們打開(kāi)游戲App或開(kāi)始運(yùn)行游戲軟件時(shí),會(huì)遇到什么樣的畫面:出現(xiàn)游戲Logo、播放游戲片頭、加載游戲數(shù)據(jù)、出現(xiàn)游戲主畫面、等待玩家登錄游戲、進(jìn)入游戲主畫面,接下來(lái)玩家可能是在大地圖上打怪或進(jìn)入副本刷關(guān)卡……。游戲畫面轉(zhuǎn)換如圖3-1所示。 圖3-1 游戲畫面轉(zhuǎn)換就以上面的說(shuō)明為例,我們可規(guī)劃出下面數(shù)個(gè)場(chǎng)景,每個(gè)場(chǎng)景分別負(fù)責(zé)多項(xiàng)功能的執(zhí)行,如圖3-2所示。 圖3-2 每個(gè)場(chǎng)景負(fù)責(zé)執(zhí)行的游戲功能? 登錄場(chǎng)景:負(fù)責(zé)游戲片頭、加載游戲數(shù)據(jù)、出現(xiàn)游戲主畫面、等待玩家登錄游戲。? 主畫面場(chǎng)景:負(fù)責(zé)進(jìn)入游戲畫面、玩家在主城/主畫面中的操作、在地圖上打怪打?qū)?hellip;…? 戰(zhàn)斗場(chǎng)景:負(fù)責(zé)與玩家組隊(duì)之后進(jìn)入副本關(guān)卡、挑戰(zhàn)王怪……在游戲場(chǎng)景規(guī)劃完成后,就可以利用“狀態(tài)圖”將各場(chǎng)景的關(guān)系連接起來(lái),并且說(shuō)明它們之間的轉(zhuǎn)換條件以及狀態(tài)轉(zhuǎn)換的流程,如圖3-3所示。 圖3-3 各場(chǎng)景轉(zhuǎn)換條件以及狀態(tài)轉(zhuǎn)換的“狀態(tài)圖”即便我們換了一個(gè)游戲類型來(lái)實(shí)現(xiàn),一樣可以使用相同的場(chǎng)景分類方式,將游戲功能進(jìn)行歸類,例如:卡牌游戲可按如下分類:? 登錄場(chǎng)景:負(fù)責(zé)游戲片頭、加載游戲數(shù)據(jù)、出現(xiàn)游戲主畫面、等待玩家登錄游戲。? 主畫面場(chǎng)景:玩家抽卡片、合成卡牌、查看卡牌……? 戰(zhàn)斗場(chǎng)景:挑戰(zhàn)關(guān)卡、卡片對(duì)戰(zhàn)……轉(zhuǎn)珠游戲可按如下分類:? 登錄場(chǎng)景:負(fù)責(zé)游戲片頭、加載游戲數(shù)據(jù)、出現(xiàn)游戲主畫面、等待玩家登錄游戲。? 主畫面場(chǎng)景:查看關(guān)卡進(jìn)度、關(guān)卡信息、商城、抽轉(zhuǎn)珠……? 戰(zhàn)斗場(chǎng)景:挑戰(zhàn)關(guān)卡、轉(zhuǎn)珠對(duì)戰(zhàn)……當(dāng)然,如果是更復(fù)雜的單機(jī)版游戲或大型多人在線游戲(MMORPG),還可以再細(xì)分出多個(gè)場(chǎng)景來(lái)負(fù)責(zé)對(duì)應(yīng)的游戲功能。切分場(chǎng)景的好處將游戲中不同的功能分類在不同的場(chǎng)景中來(lái)執(zhí)行,除了可以將游戲功能執(zhí)行時(shí)需要的環(huán)境明確分類之外,“重復(fù)使用”也是使用場(chǎng)景轉(zhuǎn)換的好處之一。從上面幾個(gè)例子中可以看出,“登錄場(chǎng)景”幾乎是每款游戲必備的場(chǎng)景之一。而一般在登錄場(chǎng)景中,會(huì)實(shí)現(xiàn)游戲初始化功能或玩家登錄游戲時(shí)需要執(zhí)行的功能,例如:? 單機(jī)游戲:登錄場(chǎng)景可以有加載游戲數(shù)據(jù)、讓玩家選擇存盤、進(jìn)入游戲等步驟。? 在線游戲:登錄場(chǎng)景包含了許多復(fù)雜的在線登錄流程,比如使用第三方認(rèn)證系統(tǒng)、使用玩家自定義賬號(hào)、與服務(wù)器連接、數(shù)據(jù)驗(yàn)證……對(duì)于大多數(shù)的游戲開(kāi)發(fā)公司來(lái)說(shuō),登錄場(chǎng)景實(shí)現(xiàn)的功能,會(huì)希望通用于不同的游戲開(kāi)發(fā)項(xiàng)目,使其保持流程的一致性。尤其對(duì)于在線游戲這種類型的項(xiàng)目而言,由于登錄流程較為復(fù)雜,若能將各項(xiàng)目共同的部分(場(chǎng)景)獨(dú)立出來(lái),由專人負(fù)責(zé)開(kāi)發(fā)維護(hù)并同步更新給各個(gè)項(xiàng)目,那么效率就能獲得提升,也是比較安全的方式。在項(xiàng)目開(kāi)發(fā)時(shí),若是能重復(fù)使用這些已經(jīng)設(shè)計(jì)良好的場(chǎng)景,將會(huì)減少許多開(kāi)發(fā)時(shí)間。更多的優(yōu)點(diǎn)將在后續(xù)章節(jié)中說(shuō)明。本書范例場(chǎng)景的規(guī)劃在本書范例中,《P級(jí)陣地》規(guī)劃了3個(gè)場(chǎng)景,如圖3-4所示。 圖3-4 《P級(jí)陣地》規(guī)劃的3個(gè)場(chǎng)景? 開(kāi)始場(chǎng)景(StarScene):GameLoop游戲?qū)ο?GameObject)的所在,游戲啟動(dòng)及相關(guān)游戲設(shè)置的加載。? 主畫面場(chǎng)景(MainMenuScene):顯示游戲名稱和“開(kāi)始”按鈕。? 戰(zhàn)斗場(chǎng)景(BattleScene):游戲主要執(zhí)行的場(chǎng)景。3.1.2 游戲場(chǎng)景可能的實(shí)現(xiàn)方式實(shí)現(xiàn)Unity3D的場(chǎng)景轉(zhuǎn)換較為直接的方式如下:Listing 3-1 一般場(chǎng)景控制的寫法public class SceneManager{ private string m_state = "開(kāi)始"; // 改換場(chǎng)景 public void ChangeScene(string StateName) { m_state = StateName;
switch(m_state) { case "菜單": Application.LoadLevel(“MainMenuScene”); break; case "主場(chǎng)景": Application.LoadLevel(“GameScene”); break; } } // 更新 public void Update() { switch(m_state) { case "開(kāi)始": //... break; case "菜單": //... break; case "主場(chǎng)景": //... break; } }}
上述的實(shí)現(xiàn)方式會(huì)有以下缺點(diǎn):只要增加一個(gè)狀態(tài),則所有switch(m_state)的程序代碼都需要增加對(duì)應(yīng)的程序代碼。與每一個(gè)狀態(tài)有關(guān)的對(duì)象,都必須在SceneManager類中被保留,當(dāng)這些對(duì)象被多個(gè)狀態(tài)共享時(shí),可能會(huì)產(chǎn)生混淆,不太容易識(shí)別是由哪個(gè)狀態(tài)設(shè)置的,造成游戲程序調(diào)試上的困難。每一個(gè)狀態(tài)可能使用不同的類對(duì)象,容易造成SceneManager類過(guò)度依賴其他類,讓SceneManager類不容易移植到其他項(xiàng)目中。為了避免出現(xiàn)上述缺點(diǎn),修正的目標(biāo)會(huì)希望使用一個(gè)“場(chǎng)景類”來(lái)負(fù)責(zé)維護(hù)一個(gè)場(chǎng)景,讓與此場(chǎng)景相關(guān)的程序代碼和對(duì)象能整合在一起。這個(gè)負(fù)責(zé)維護(hù)的“場(chǎng)景類”,其主要工作如下:? 場(chǎng)景初始化;? 場(chǎng)景結(jié)束后,負(fù)責(zé)清除資源;? 定時(shí)更新游戲邏輯單元;? 轉(zhuǎn)換到其他場(chǎng)景;? 其他與該場(chǎng)景有關(guān)的游戲?qū)崿F(xiàn)。由于在范例程序中我們規(guī)劃了3個(gè)場(chǎng)景,所以會(huì)產(chǎn)生對(duì)應(yīng)的3個(gè)“場(chǎng)景類”,但如何讓這3個(gè)“場(chǎng)景類”相互合作、彼此轉(zhuǎn)換呢?我們可以使用GoF的狀態(tài)模式(State)來(lái)解決這些問(wèn)題。3.2 狀態(tài)模式(State)狀態(tài)模式(State),在多數(shù)的設(shè)計(jì)模式書籍中都會(huì)提及,它也是游戲程序設(shè)計(jì)中應(yīng)用最頻繁的一種模式。主要是因?yàn)?ldquo;狀態(tài)”經(jīng)常被應(yīng)用在游戲設(shè)計(jì)的許多環(huán)節(jié)中,包含AI人工智能狀態(tài)、賬號(hào)登錄狀態(tài)、角色狀態(tài)……3.2.1 狀態(tài)模式(State)的定義狀態(tài)模式(State),在GoF中的解釋是:“讓一個(gè)對(duì)象的行為隨著內(nèi)部狀態(tài)的改變而變化,而該對(duì)象也像是換了類一樣”。如果將GoF對(duì)狀態(tài)模式(State)的定義改以游戲的方式來(lái)解釋,就會(huì)像下面這樣:“當(dāng)?shù)卖斠?對(duì)象)由人形變化為獸形狀態(tài)(內(nèi)部狀態(tài)改變)時(shí),他所施展的技能(對(duì)象的行為)也會(huì)有所變化,玩家此時(shí)就像是在操作另一個(gè)不同的角色(像是換了類)”。“德魯伊“是一種經(jīng)常出現(xiàn)在角色扮演游戲(RPG)中的角色名稱。變化外形是他們常使用的能力,通過(guò)外形的變化,使德魯伊具備了轉(zhuǎn)換為其他形體的能力,而變化為“獸形”是比較常見(jiàn)的游戲設(shè)計(jì)。當(dāng)玩家決定施展外形轉(zhuǎn)換能力時(shí),德魯伊?xí)M(jìn)入“獸形狀態(tài)”,這時(shí)候的德魯伊?xí)?ldquo;獸形”來(lái)表現(xiàn)其行為,包含移動(dòng)和攻擊施展的方式;當(dāng)玩家決定轉(zhuǎn)換回人形時(shí),德魯伊?xí)?fù)原為一般形態(tài),繼續(xù)與游戲世界互動(dòng)。所以,變化外形的能力可以看成是德魯伊的一種“內(nèi)部狀態(tài)的轉(zhuǎn)換”。通過(guò)變化外形的結(jié)果,角色表現(xiàn)出另外一種行為模式,而這一切的轉(zhuǎn)化過(guò)程都可以由德魯伊的內(nèi)部控制功能來(lái)完成,玩家不必理解這個(gè)轉(zhuǎn)化過(guò)程。但無(wú)論怎么變化,玩家操作的角色都是德魯伊,并不會(huì)因?yàn)樗麅?nèi)部狀態(tài)的轉(zhuǎn)變而有所差異。當(dāng)某個(gè)對(duì)象狀態(tài)改變時(shí),雖然它“表現(xiàn)的行為”會(huì)有所變化,但是對(duì)于客戶端來(lái)說(shuō),并不會(huì)因?yàn)檫@樣的變化,而改變對(duì)它的“操作方法”或“信息溝通”的方式。也就是說(shuō),這個(gè)對(duì)象與外界的對(duì)應(yīng)方式不會(huì)有任何改變。但是,對(duì)象的內(nèi)部確實(shí)是會(huì)通過(guò)“更換狀態(tài)類對(duì)象”的方式來(lái)進(jìn)行狀態(tài)的轉(zhuǎn)換。當(dāng)狀態(tài)對(duì)象更換到另一個(gè)類時(shí),對(duì)象就會(huì)通過(guò)新的狀態(tài)類,表現(xiàn)出它在這個(gè)狀態(tài)下該有的行為。但這一切只會(huì)發(fā)生在對(duì)象內(nèi)部,對(duì)客戶端來(lái)說(shuō),不需要了解這些狀態(tài)轉(zhuǎn)換的過(guò)程及對(duì)應(yīng)的方式。3.2.2 狀態(tài)模式(State)的說(shuō)明狀態(tài)模式(State)的結(jié)構(gòu)如圖3-5所示。 圖3-5 狀態(tài)模式的結(jié)構(gòu)圖參與者的說(shuō)明如下:? Context(狀態(tài)擁有者)? 是一個(gè)具有“狀態(tài)”屬性的類,可以制定相關(guān)的接口,讓外界能夠得知狀態(tài)的改變或通過(guò)操作讓狀態(tài)改變。? 有狀態(tài)屬性的類,例如:游戲角色有潛行、攻擊、施法等狀態(tài);好友上線、脫機(jī)、忙碌等狀態(tài);GoF使用TCP聯(lián)網(wǎng)為例,有已連接、等待連接、斷線等狀態(tài)。這些類中會(huì)有一個(gè)ConcreteState[X]子類的對(duì)象為其成員,用來(lái)代表當(dāng)前的狀態(tài)。? State(狀態(tài)接口類):制定狀態(tài)的接口,負(fù)責(zé)規(guī)范Context(狀態(tài)擁有者)在特定狀態(tài)下要表現(xiàn)的行為。? ConcreteState(具體狀態(tài)類)? 繼承自State(狀態(tài)接口類)。? 實(shí)現(xiàn)Context(狀態(tài)擁有者)在特定狀態(tài)下該有的行為。例如,實(shí)現(xiàn)角色在潛行狀態(tài)時(shí)該有的行動(dòng)變緩、3D模型變半透明、不能被敵方角色察覺(jué)等行為。3.2.3 狀態(tài)模式(State)的實(shí)現(xiàn)范例首先定義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類中,擁有一個(gè)State屬性用來(lái)代表當(dāng)前的狀態(tài),外界可以通過(guò)Request方法,讓Context類呈現(xiàn)當(dāng)前狀態(tài)下的行為。SetState方法可以指定Context類當(dāng)前的狀態(tài),而State狀態(tài)接口類則用來(lái)定義每一個(gè)狀態(tài)該有的行為: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);}在產(chǎn)生State類對(duì)象時(shí),可以傳入Context類對(duì)象,并將其指定給State的類成員m_Context,讓State類在后續(xù)的操作中,可以獲取Context對(duì)象的信息或操作Context對(duì)象。然后定義Handle抽象方法,讓繼承的子類可以重新定義該方法,來(lái)呈現(xiàn)各自不同的狀態(tài)行為。定義3個(gè)繼承自State類的子類:Listing 3-4 定義3個(gè)狀態(tài)(State.cs)// 狀態(tài)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)); }}
// 狀態(tài)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)); } }
// 狀態(tài)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個(gè)子類,都要重新定義父類State的Handle抽象方法,用來(lái)表示在各自狀態(tài)下的行為。在范例中,我們先讓它們各自顯示不同的信息(代表當(dāng)前的狀態(tài)行為),再按照本身狀態(tài)的行為定義來(lái)判斷是否要通知Context對(duì)象轉(zhuǎn)換到另一個(gè)狀態(tài)。Context類中提供了一個(gè)SetState方法,讓外界能夠設(shè)置Context對(duì)象當(dāng)前的狀態(tài),而所謂的“外界”,也可以是由另一個(gè)State狀態(tài)來(lái)調(diào)用。所以實(shí)現(xiàn)上,狀態(tài)的轉(zhuǎn)換可以有下列兩種方式:? 交由Context類本身,按條件在各狀態(tài)之間轉(zhuǎn)換;? 產(chǎn)生Context類對(duì)象時(shí),馬上指定初始狀態(tài)給Context對(duì)象,而在后續(xù)執(zhí)行過(guò)程中的狀態(tài)轉(zhuǎn)換則交由State對(duì)象負(fù)責(zé),Context對(duì)象不再介入。筆者在實(shí)現(xiàn)時(shí),大部分情況下會(huì)選擇第2種方式,原因在于:狀態(tài)對(duì)象本身比較清楚“在什么條件下,可以讓Context對(duì)象轉(zhuǎn)移到另一個(gè)State狀態(tài)”。所以在每個(gè)ConcreteState類的程序代碼中,可以看到“狀態(tài)轉(zhuǎn)換條件”的判斷,以及設(shè)置哪一個(gè)ConcreteState對(duì)象成為新的狀態(tài)。每個(gè)ConcreteState狀態(tài)都可以保持自己的屬性值,作為狀態(tài)轉(zhuǎn)換或展現(xiàn)狀態(tài)行為的依據(jù),不會(huì)與其他的ConcreteState狀態(tài)混用,在維護(hù)時(shí)比較容易理解。因?yàn)榕袛鄺l件及狀態(tài)屬性都被轉(zhuǎn)換到ConcreteState類中,故而可縮減Context類的大小。4個(gè)類定義好之后,我們可以通過(guò)測(cè)試范例來(lái)看看客戶端程序會(huì)怎樣利用這個(gè)設(shè)計(jì):Listing 3-5 State的測(cè)試范例(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 ); }首先產(chǎn)生Context對(duì)象theContext,并立即設(shè)置為ConcreteStateA狀態(tài);然后調(diào)用Context類的Request方法,并傳入作為“狀態(tài)轉(zhuǎn)換判斷”用途的參數(shù),讓當(dāng)前狀態(tài)(ConcreteStateA)判斷是否要轉(zhuǎn)移到ConcreteStateB;調(diào)用幾次Request方法,并傳入不同的參數(shù)。從輸出的信息中可以看到,Context對(duì)象的狀態(tài)由ConcreteStateA按序轉(zhuǎn)換到ConcreteStateB、 ConcreteStateC狀態(tài),回到ConcreteStateA狀態(tài)。 State測(cè)試范例產(chǎn)生的信息 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 使用狀態(tài)模式(State)實(shí)現(xiàn)游戲場(chǎng)景的轉(zhuǎn)換在Unity3D的環(huán)境中,游戲只會(huì)在一個(gè)場(chǎng)景中運(yùn)行,所以我們可以讓每個(gè)場(chǎng)景都由一個(gè)“場(chǎng)景類”來(lái)負(fù)責(zé)維護(hù)。此時(shí),如果將場(chǎng)景類當(dāng)成“狀態(tài)”來(lái)比喻的話,那么就可以利用狀態(tài)模式(State)的轉(zhuǎn)換原理,來(lái)完成場(chǎng)景轉(zhuǎn)換的功能。由于每個(gè)場(chǎng)景所負(fù)責(zé)執(zhí)行的功能不同,通過(guò)狀態(tài)模式(State)的狀態(tài)轉(zhuǎn)移,除了可以實(shí)現(xiàn)游戲內(nèi)部功能的轉(zhuǎn)換外,對(duì)于客戶端來(lái)說(shuō),也不必根據(jù)不同的游戲狀態(tài)來(lái)編寫不同的程代碼,同時(shí)也減少了外界對(duì)于不同游戲狀態(tài)的依賴性。而原本的Unity3D場(chǎng)景轉(zhuǎn)換判斷功能,可以在各自的場(chǎng)景類中完成,并且狀態(tài)模式(State)同時(shí)間也只會(huì)讓一個(gè)狀態(tài)存在(同時(shí)間只會(huì)有一個(gè)狀態(tài)在運(yùn)行),因此可以滿足Unity3D執(zhí)行時(shí)只能有一個(gè)場(chǎng)景(狀態(tài))存在的要求。3.3.1 SceneState的實(shí)現(xiàn)《P級(jí)陣地》的場(chǎng)景分成3個(gè):開(kāi)始場(chǎng)景(StarScene)、主畫面場(chǎng)景(MainM