![設(shè)計(jì)模式在游戲設(shè)計(jì)中的應(yīng)用.doc_第1頁(yè)](http://file.renrendoc.com/FileRoot1/2020-1/12/7b5cb1eb-96df-4965-95f1-4adfebac072e/7b5cb1eb-96df-4965-95f1-4adfebac072e1.gif)
![設(shè)計(jì)模式在游戲設(shè)計(jì)中的應(yīng)用.doc_第2頁(yè)](http://file.renrendoc.com/FileRoot1/2020-1/12/7b5cb1eb-96df-4965-95f1-4adfebac072e/7b5cb1eb-96df-4965-95f1-4adfebac072e2.gif)
![設(shè)計(jì)模式在游戲設(shè)計(jì)中的應(yīng)用.doc_第3頁(yè)](http://file.renrendoc.com/FileRoot1/2020-1/12/7b5cb1eb-96df-4965-95f1-4adfebac072e/7b5cb1eb-96df-4965-95f1-4adfebac072e3.gif)
![設(shè)計(jì)模式在游戲設(shè)計(jì)中的應(yīng)用.doc_第4頁(yè)](http://file.renrendoc.com/FileRoot1/2020-1/12/7b5cb1eb-96df-4965-95f1-4adfebac072e/7b5cb1eb-96df-4965-95f1-4adfebac072e4.gif)
![設(shè)計(jì)模式在游戲設(shè)計(jì)中的應(yīng)用.doc_第5頁(yè)](http://file.renrendoc.com/FileRoot1/2020-1/12/7b5cb1eb-96df-4965-95f1-4adfebac072e/7b5cb1eb-96df-4965-95f1-4adfebac072e5.gif)
已閱讀5頁(yè),還剩10頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Java設(shè)計(jì)模式論文完成人班級(jí)學(xué)號(hào)設(shè)計(jì)模式在游戲設(shè)計(jì)中的應(yīng)用1. 程序設(shè)計(jì)目標(biāo)與使用說(shuō)明1.1前言設(shè)計(jì)模式在軟件工程中有著廣泛的應(yīng)用,如java的MVC框架,用到了Observer模式,c#的LINQ,用到了Iterator模式,甚至連c+的STL中Iterator模式都有廣泛的應(yīng)用,但是我對(duì)這些軟件工程方面的應(yīng)用不是很感興趣,我感興趣的是設(shè)計(jì)模式在游戲開(kāi)發(fā)中的應(yīng)用,因此我嘗試著使用Strategy模式和Abstract Factory模式來(lái)設(shè)計(jì)一個(gè)角色扮演游戲,來(lái)體驗(yàn)設(shè)計(jì)模式在游戲開(kāi)發(fā)中的優(yōu)勢(shì)之處,由于我更善于使用c#編程,因此游戲?qū)⒁詂#為基礎(chǔ),代碼運(yùn)行環(huán)境是VS2010。我始終覺(jué)得,設(shè)計(jì)模式的作用是為了方便開(kāi)發(fā),如果因?yàn)樵O(shè)計(jì)模式而使得開(kāi)發(fā)變得復(fù)雜,那就得不償失了,當(dāng)然由于水平有限,我所能涉及到的只是游戲與設(shè)計(jì)模式應(yīng)用的冰山一角,更深入的知識(shí),需要我在以后的學(xué)習(xí)中不斷的去深入和探究。1.2工程說(shuō)明工程開(kāi)發(fā)環(huán)境是vs2010 32位旗艦中文版,項(xiàng)目是c#控制臺(tái)應(yīng)用程序。打開(kāi)項(xiàng)目需要先打開(kāi)電子檔中的RpgGame文件夾,雙擊RpgGame.sln打開(kāi)打開(kāi)工程后,具體的源代碼在Program.cs中:2. 游戲具體實(shí)現(xiàn)在游戲開(kāi)發(fā)的開(kāi)始,我設(shè)定構(gòu)建一個(gè)魔法世界的游戲,游戲中的角色有魔法師、戰(zhàn)士、牧師三種職業(yè),人物有人類、精靈兩種種族。三種職業(yè)需要施展不同的魔法,因此需要用Strategy模式將角色行為和技能施展分離開(kāi)來(lái);而兩個(gè)種族由于有著大同小異的外形,所以可以用Abstract Factory模式提煉出抽象的“身體”和具體的人類和精靈的實(shí)現(xiàn)。2.1.角色技能與Strategy模式1) 繼承實(shí)現(xiàn)的問(wèn)題在開(kāi)始游戲之前,我為玩家設(shè)定三種職業(yè):魔法師、戰(zhàn)士、牧師。正如字面上所看到的,魔法師擅長(zhǎng)使用魔法攻擊,戰(zhàn)士擅長(zhǎng)使用物理攻擊,而牧師則擅長(zhǎng)治療。根據(jù)面向?qū)ο缶幊趟枷?,我需要先定義一個(gè)抽象類作為基類,將三個(gè)職業(yè)的實(shí)現(xiàn)作為子類,以實(shí)現(xiàn)代碼的重用。對(duì)于抽象基類來(lái)說(shuō),首先要確定的是角色應(yīng)該擁有的獨(dú)立于職業(yè)的能力: ShowInfo():顯示角色基本信息,如魔法師顯示:This is a magician. Run():讓角色行走,顯示:Player is running. Stay():讓角色站立,顯示:Player is standing.一般來(lái)說(shuō),設(shè)計(jì)時(shí)需要遵循這樣的原則:1. 對(duì)于所有繼承類都有,但是每個(gè)繼承類的實(shí)現(xiàn)各不相同的方法,我們?cè)诨愔兄唤o出定義,不給出實(shí)現(xiàn),而在繼承類中予以實(shí)現(xiàn)。換言之,就是在基類中定義一個(gè)抽象方法。2. 對(duì)于所有繼承類都有,并且每個(gè)繼承類的實(shí)現(xiàn)完全相同的方法,我們直接在基類中實(shí)現(xiàn)它,而由子類去繼承,以實(shí)現(xiàn)代碼重用。很顯然,每個(gè)職業(yè)都擁有上邊定義的三種能力,其中ShowInfo()對(duì)于每種職業(yè)都不相同,而Run()和Stay()對(duì)于每種職業(yè)都相同,于是構(gòu)建基類,實(shí)現(xiàn)下面的UML設(shè)計(jì):2) 基類實(shí)現(xiàn)和繼承實(shí)現(xiàn)的問(wèn)題實(shí)現(xiàn)基本功能后,考慮讓所有的職業(yè)可以實(shí)現(xiàn)技能的釋放,因此需要添加一個(gè)新的方法ReleaseSkills(),很容易想到的是在基類Charactor中添加方法ReleaseSkills(),這樣可以實(shí)現(xiàn)代碼的重用,但是很容易就可以發(fā)現(xiàn)三個(gè)子類釋放技能的方式并不相同,將方法放在基類中不但沒(méi)有解決問(wèn)題,反而使問(wèn)題復(fù)雜了,將問(wèn)題抽象化,可以得到這樣的描述:給基類添加實(shí)體方法,使得不應(yīng)該擁有此方法的子類也擁有了此方法,也使得所有子類方法擁有了完全一樣的實(shí)現(xiàn)。當(dāng)然可以有另外一種解決的方法,那就是在每個(gè)子類中定義各自的ReleaseSkills()覆蓋基類的方法,這樣似乎解決了問(wèn)題,但如果有一天需要加入一個(gè)新的職業(yè),比如騎士,那就需要重新定義它的ReleaseSkills(),這樣的缺陷顯而易見(jiàn):v 沒(méi)有實(shí)現(xiàn)代碼重用,如果新添加角色的話,就需要重新寫(xiě)代碼進(jìn)行覆蓋。v 如果釋放技能的方法需要改動(dòng),那么就不得不在子類中都重新寫(xiě)一遍。v 如果新定義一種職業(yè)不需要釋放技能,但是它也繼承了ReleaseSkills()的方法,即使在子類中定義一個(gè)空的ReleaseSkills()方法,仍然會(huì)暴露出它擁有ReleaseSkills()的能力。3) 引入接口繼承的使用會(huì)帶來(lái)很多問(wèn)題,那么嘗試使用接口來(lái)實(shí)現(xiàn)。首先定義ReleaseSkills()接口,然后在子類中實(shí)現(xiàn)。當(dāng)然這里沒(méi)有考慮戰(zhàn)士釋放技能的問(wèn)題,事實(shí)上戰(zhàn)士一般是不需要釋放技能的能力的。由此我們得到下面的UML圖:使用接口雖然解決了部分問(wèn)題,但是有更多的問(wèn)題沒(méi)有解決,例如,子類仍然要重新寫(xiě)自己的釋放技能的實(shí)現(xiàn)代碼,所以為了使釋放技能與角色本身分離開(kāi)來(lái),就需要將釋放技能的接口封裝起來(lái)。4) 封裝行為面向?qū)ο蟮囊粋€(gè)原則是封裝變化,在當(dāng)前的情況中,ReleaseSkills()這個(gè)行為是不斷變化的,那么在設(shè)計(jì)的過(guò)程中我就需要想辦法將它封裝起來(lái)。實(shí)現(xiàn)此接口的類不再是定義的角色的基類或者子類,而是專用于ReleaseSkills()這個(gè)行為的類。如下圖所示:在這里,接口的實(shí)現(xiàn)放在了它自己的繼承體系中,而不是放到角色類里邊,每一個(gè)實(shí)現(xiàn)接口的類完成一個(gè)特定的ReleaseSkills()的實(shí)現(xiàn),比如ReleaseMagic類打印一句:Magic has been released,ReleaseLight類(光系魔法,也就是治療魔法)打印一句:Light has been released,而ReleaseNothing類對(duì)應(yīng)不釋放魔法的戰(zhàn)士,打印一句:I cant release magic。下面要做的就是將這個(gè)技能釋放的體系與角色體系結(jié)合起來(lái),具體就是在基類中聲明Skills類型的變量,如下圖所示:注意到 Character 類中仍有一個(gè)ReleaseSkills()方法,但是這個(gè)方法與之前的ReleaseSkills()方法不同: 它不是用來(lái)給子類去覆蓋的。 我們通過(guò)Character的ReleaseSkills()方法實(shí)際去調(diào)用 Skills 接口的ReleaseSkills()方法(實(shí)際上調(diào)用了其實(shí)體類的ReleaseSkills()方法)。具體類定義的代碼如下:/定義釋放技能的接口 public interface Skills void ReleaseSkills(); /定義釋放魔法的類 public class ReleaseMagic : Skills public void ReleaseSkills() Console.WriteLine(Magic has been released.); /定義釋放治療的類 public class ReleaseLight : Skills public void ReleaseSkills() Console.WriteLine(Light has been released.); /定義不釋放技能的類 public class ReleaseNothing : Skills public void ReleaseSkills() Console.WriteLine(I cant release skills.); /角色基類 public abstract class Charactor protected Skills releaseSkills; /釋放技能,通過(guò)接口來(lái)調(diào)用 public void ReleaseSkills() releaseSkills.ReleaseSkills(); /動(dòng)態(tài)更改角色的釋放技能能力 public void ChangeSkills(Skills newSkill) Console.WriteLine(I have Changed my skills.); releaseSkills = newSkill; public void Run() Console.WriteLine(I am Running.); public void Stay() Console.WriteLine(I am standing.); abstract public void ShowInfo(); /顯示角色信息 /定義魔法師 public class Magician : Charactor public Magician() /初始化來(lái)自基類的Skills變量 releaseSkills = new ReleaseMagic(); public override void ShowInfo() Console.WriteLine(I am a Magician.); /定義戰(zhàn)士 public class Warrior : Charactor public Warrior() releaseSkills = new ReleaseNothing(); public override void ShowInfo() Console.WriteLine(I am a Warrior.); /定義牧師 public class Priest : Charactor public Priest() releaseSkills = new ReleaseLight(); public override void ShowInfo() Console.WriteLine(I am a Priest.); 到現(xiàn)在可以有一個(gè)總結(jié),上邊封裝的Skills接口,實(shí)際上使用了Strategy模式,正如Strategy模式的官方定義:Strategy模式定義了一系列的算法,將它們每一個(gè)進(jìn)行封裝,并使它們可以相互交換。Strategy模式使得算法不依賴于使用它的客戶端。2.2人物構(gòu)造與 Abstract Factory模式1) 面向?qū)崿F(xiàn)的方式當(dāng)設(shè)定完職業(yè)之后,我需要設(shè)定角色的種族,為了簡(jiǎn)單起見(jiàn),在這里我只設(shè)定了精靈和人類,當(dāng)然如果以后要擴(kuò)展的話,還可以加入矮人、獸人、魔族等種族。對(duì)比精靈和人類可以發(fā)現(xiàn)他們的相同和不同之處:l 都有頭部、身軀和四肢,面部都有五官。l 精靈的耳朵、眼睛、皮膚和身材是異于人類的。由此可以假定角色身體由三部分組成:頭部(Head)、身體(Body)、皮膚(Skin)。于是得到下面的設(shè)計(jì):2) 抽象組成身體的實(shí)體類我發(fā)現(xiàn)這樣做,每個(gè)角色與他的身體部件是牢牢綁定在一起的,每創(chuàng)建一個(gè)角色,我都需要為它先行創(chuàng)建所有其復(fù)合的類(組成身體的實(shí)體類,比如HumanHead)。按照面向?qū)ο蟮乃枷?,我想到?yīng)該對(duì)這一過(guò)程進(jìn)行封裝,將創(chuàng)建角色部件這件事委派給其他的類來(lái)完成。觀察上圖,我發(fā)現(xiàn)盡管角色不同,但它們都是由三個(gè)部分構(gòu)成,所以,我所能想到的實(shí)現(xiàn)這一過(guò)程的第一步,就是對(duì)組成身體的實(shí)體類進(jìn)行抽象,定義三個(gè)接口:Head、Body、Skin,代表身體的三個(gè)部分,并且讓Human和Elf的實(shí)體類去實(shí)現(xiàn)這個(gè)接口:通過(guò)上圖可以發(fā)現(xiàn),發(fā)現(xiàn)盡管定義了接口,但是如果角色Human和Elf仍然與接口的實(shí)體類關(guān)聯(lián),那么效果與面向?qū)崿F(xiàn)完全相同。而且還有一個(gè)問(wèn)題是Human與Elf相似的地方很多,除了名字不同其余的完全一樣,那么久可以將它們合并成一個(gè)類,起名叫Race(種族),設(shè)計(jì)再次變成下面這樣:3) 創(chuàng)建工廠類到這里現(xiàn)在結(jié)構(gòu)已經(jīng)很完善了,我定義了接口來(lái)解決問(wèn)題,也沒(méi)有為不同的角色創(chuàng)建多個(gè)不同的類,而只要在Race的構(gòu)造函數(shù)中為代表身體部件的變量賦不同的值,就可以創(chuàng)建不同種族的角色。這時(shí)候,如果有一個(gè)類可以專門(mén)負(fù)責(zé)創(chuàng)建身體部件這件事,當(dāng)想要?jiǎng)?chuàng)建角色的時(shí)候,將這個(gè)類傳遞給Race的構(gòu)造函數(shù)就可以了。設(shè)定創(chuàng)建Human身體組成部分的類稱作:HumanPartsFactory,創(chuàng)建Elf身體部分的類稱作ElfPartsFacotry。那么它們應(yīng)該是這樣的:但是Race的構(gòu)造函數(shù)只能接受一個(gè)HumanPartsFactory類型的參數(shù),為了傳遞ElfPartsFactory,將不得不再添加一個(gè)接受ElfPartsFactory類型的構(gòu)造函數(shù)。這樣顯然不好,所以應(yīng)該建立一個(gè)抽象的種族工廠:4) Abstract Factory設(shè)計(jì)模式上面做的這些,使用到了一個(gè)新的設(shè)計(jì)模式:Abstract Factory。它的正式定義是這樣的:提供一個(gè)接口用于創(chuàng)建一系列相互關(guān)聯(lián)或者相互依賴的對(duì)象,而不需要指定它們的實(shí)體類。最后完整的UML設(shè)計(jì)應(yīng)該是這樣子的:下面是代碼實(shí)現(xiàn):/定義構(gòu)成身體部分的接口 public interface Head string name get; public interface Body string name get; public interface Skin string name get; /組成human的類 public class HumanHead : Head public string name get return Human Head; public class HumanBody : Body public string name get return Human Body; public class HumanSkin : Skin public string name get return Human Skin; /組成Elf的類 public class ElfHead : Head public string name get return Elf Head; public class ElfBody : Body public string name get return Elf Body; public class ElfSkin : Skin public string name get return Elf Skin; /定義工廠接口 public interface RaceFactory Head CreateHead(); Body CreateBody(); Skin CreateSkin(); /定義human的身體工廠類 public class HumanFactory : RaceFactory public Head CreateHead() return new HumanHead(); public Body CreateBody() return new HumanBody(); public Skin CreateSkin() return new HumanSkin(); /定義Elf的身體工廠類 public class ElfFactory : RaceFactory public Head CreateHead() return new ElfHead(); public Body CreateBody() return new ElfBody(); public Skin CreateSkin() return new ElfSkin(); /定義Race類 public class Race public Head head; public Body body; public Skin skin; public Race(RaceFactory raceFactory) head = raceFactory.CreateHead(); body = raceFactory.CreateBody(); skin = raceFactory.CreateSkin(); 為了方便的調(diào)用以上定義的技能類和種族類,我需要建立一個(gè)Race類來(lái)包含上邊兩個(gè)類的實(shí)現(xiàn),代碼如下: class Player public Charactor career; public Race race; /為玩家初始化 public Player(Charactor charactor, Race playerRace) career = charactor; race = playerRace; 將兩部分設(shè)計(jì)模式結(jié)合起來(lái),我們就可以在實(shí)際中很方便的應(yīng)用它們,例如如果我想定義一個(gè)玩家,職業(yè)是魔法師,種族是精靈,那么可以這樣:/定義一個(gè)新的玩家,職業(yè)是魔法師,種族是精靈Player player = new Player(new Magician(), new Race(new ElfFactory();當(dāng)需要展示這個(gè)玩家的信息的時(shí)候,直接調(diào)用方法就可以了:player.career.S
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 聽(tīng)評(píng)課記錄九年級(jí)物理
- 人教版數(shù)學(xué)七年級(jí)下冊(cè)知識(shí)點(diǎn)
- 粵教版地理八年級(jí)下冊(cè)第六章第4節(jié)《西部地區(qū)》聽(tīng)課評(píng)課記錄4
- 湘教版數(shù)學(xué)八年級(jí)下冊(cè)1.2《直角三角形的性質(zhì)和判定(II)》聽(tīng)評(píng)課記錄
- 小學(xué)二年級(jí)數(shù)學(xué)100道口算題
- 湘教版數(shù)學(xué)七年級(jí)下冊(cè)2.2.2《完全平方公式》聽(tīng)評(píng)課記錄1
- 人教版數(shù)學(xué)七年級(jí)下冊(cè)聽(tīng)評(píng)課記錄9.1.1《 不等式及其解集》
- 2025年水利管理及技術(shù)咨詢服務(wù)項(xiàng)目合作計(jì)劃書(shū)
- 合伙開(kāi)餐飲餐館項(xiàng)目協(xié)議書(shū)范本
- 融資咨詢代理協(xié)議書(shū)范本
- 河北省邯鄲市永年區(qū)2024-2025學(xué)年九年級(jí)上學(xué)期期末考試化學(xué)試卷(含答案)
- 油漆工培訓(xùn)試題
- 2024年四川綿陽(yáng)初中學(xué)業(yè)水平考試英語(yǔ)試卷真題(含答案詳解)
- 2025年閥門(mén)和龍頭項(xiàng)目發(fā)展計(jì)劃
- 2025初級(jí)會(huì)計(jì)理論考試100題及解析
- 三兄弟分田地宅基地協(xié)議書(shū)范文
- 廣東省會(huì)計(jì)師事務(wù)所審計(jì)服務(wù)收費(fèi)標(biāo)準(zhǔn)表
- 參觀河南省博物院
- 中考數(shù)學(xué)計(jì)算題練習(xí)100道(2024年中考真題)
- 婚禮主持詞:農(nóng)村婚禮主持詞
- 匯川變頻器MD張力開(kāi)環(huán)調(diào)試
評(píng)論
0/150
提交評(píng)論