




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
-
-
摘要本文主要闡述網(wǎng)絡(luò)回合制戰(zhàn)斗系統(tǒng)的實(shí)現(xiàn),包括回合制戰(zhàn)斗系統(tǒng)的整個流程(戰(zhàn)斗開始、玩家下達(dá)戰(zhàn)斗指令、戰(zhàn)斗動畫、戰(zhàn)斗結(jié)束),和網(wǎng)絡(luò)回合制戰(zhàn)斗系統(tǒng)常見的主要功能(攻擊、使用技能、使用物品)的實(shí)現(xiàn),并且在游戲項目《PKer》中進(jìn)行實(shí)踐和測試。在開發(fā)環(huán)境方面,服務(wù)器采用國內(nèi)IOCP高性能開源框架“HP-Socket”(Windows平臺),并且連接到Mysql數(shù)據(jù)庫,客戶端采用近年比較火熱的強(qiáng)大跨平臺引擎Unity3D(2D,C#)并且使用Sqlite作為嵌入式數(shù)據(jù)庫。除此以外,本文還對戰(zhàn)斗系統(tǒng)實(shí)現(xiàn)所涉及到的相關(guān)技術(shù)如Unity引擎的協(xié)同程序、單例設(shè)計模式和分包算法進(jìn)行簡要介紹。
關(guān)鍵詞回合制戰(zhàn)斗系統(tǒng),網(wǎng)絡(luò)游戲,Unity3D,協(xié)同程序,游戲編程
ABSTRACTThisarticlemainlyexpoundstheimplementationofnetworkturn-basedcombatsystem,includingthewholeprocessofturn-basedcombatsystem(battlebegins,theplayersfightinginstructions,combatanimation,battleends),andthemainfunctionofcommon(attack,usingskills,usingitems)implementation,andinthegame"PKer"inpracticeandtestoftheproject.Intheaspectofdevelopmentenvironment,C++IOCPserverwithWindowsplatformandconnecttotheMysqldatabase,theclientusesUnity3D(2D,C#)andusesSqliteasanembeddeddatabase.Inadditiontothis,thisarticlealsoinvolvedtocombatsystemrelatedtechnologiessuchastheUnityenginecoroutines,singletondesignpatternandthesubcontractalgorithmarebrieflyintroduced.
KEYWORDSTurn-basedcombatsystem,onlinegame,Unity3D,Coroutine,Singletondesignpattern
目錄
TOC\f\h\z\t"樣式1,1,樣式2,2,樣式3,3"
前言
1
第1章緒論
2
1.1回合制游戲簡介
2
1.1.1廣義上的回合制游戲
2
1.1.2狹義上的回合制游戲
2
1.2回合制戰(zhàn)斗系統(tǒng)簡介
2
1.3實(shí)踐項目《PKer》簡介
2
第2章開發(fā)環(huán)境和部分涉及技術(shù)簡介
4
2.1開發(fā)環(huán)境簡介
4
2.2Unity協(xié)同程序
4
2.2.1Unity協(xié)同程序簡介
4
2.2.2Unity協(xié)同程序的運(yùn)用
4
2.3單例設(shè)計模式
5
2.3.1單例設(shè)計模式
5
2.3.2單例設(shè)計模式的運(yùn)用
6
2.3.3單例設(shè)計模式在Unity中的運(yùn)用
7
2.4分包算法
7
2.4.1分包的原因
7
2.4.2環(huán)形緩沖區(qū)(CircularBuffer)
7
2.4.3分包算法流程圖
9
第3章戰(zhàn)斗動畫實(shí)現(xiàn)方案的研究與對比
11
3.1研究背景
11
3.2實(shí)現(xiàn)方案一:有限狀態(tài)機(jī)
11
3.3實(shí)現(xiàn)方案二:協(xié)同程序(Coroutine)
12
3.4方案抉擇結(jié)論
13
第4章回合制網(wǎng)游戰(zhàn)斗系統(tǒng)設(shè)計
14
4.1回合制網(wǎng)游戰(zhàn)斗系統(tǒng)設(shè)計
14
4.2回合制網(wǎng)游戰(zhàn)斗系統(tǒng)服務(wù)器實(shí)現(xiàn)思路
15
4.3回合制網(wǎng)游戰(zhàn)斗系統(tǒng)客戶端實(shí)現(xiàn)思路
15
4.4戰(zhàn)斗系統(tǒng)框架結(jié)構(gòu)(以實(shí)踐項目《PKer》為例)
16
第5章回合制戰(zhàn)斗系統(tǒng)實(shí)現(xiàn)
18
5.1戰(zhàn)斗系統(tǒng)相關(guān)消息結(jié)構(gòu)體的定義
18
5.2服務(wù)器戰(zhàn)斗系統(tǒng)的實(shí)現(xiàn)
20
5.2.1服務(wù)器戰(zhàn)斗系統(tǒng)相關(guān)結(jié)構(gòu)體
20
5.2.2初始化一個戰(zhàn)局
23
5.2.3接收客戶端的戰(zhàn)斗指令消息
23
5.2.4處理戰(zhàn)斗指令并發(fā)送動畫消息
24
5.2.5說明
27
5.3客戶端戰(zhàn)斗系統(tǒng)的實(shí)現(xiàn)
27
5.3.1客戶端戰(zhàn)斗系統(tǒng)功能模塊
28
5.3.2客戶端戰(zhàn)斗系統(tǒng)相關(guān)數(shù)據(jù)類型
28
5.3.3進(jìn)入戰(zhàn)斗后初始化戰(zhàn)斗角色
29
5.3.4下達(dá)戰(zhàn)斗指令并發(fā)送戰(zhàn)斗指令消息
29
5.3.5接收戰(zhàn)斗動畫消息
30
5.3.6收到戰(zhàn)斗動畫播放消息并播放戰(zhàn)斗動畫
30
5.3.7戰(zhàn)斗動畫實(shí)現(xiàn)細(xì)述
35
第6章項目測試
39
6.1進(jìn)入戰(zhàn)斗測試
39
6.2普通攻擊功能測試
39
6.3使用技能功能測試
40
6.4使用物品功能測試
41
結(jié)論
43
參考文獻(xiàn)
44
致謝
45
前言
隨著網(wǎng)絡(luò)的普及與迅速發(fā)展,網(wǎng)絡(luò)游戲已經(jīng)成為電子游戲中的主流。網(wǎng)絡(luò)游戲的戰(zhàn)斗系統(tǒng)主要可分為即時制和回合制兩種模式。即時制戰(zhàn)斗系統(tǒng)側(cè)重于刺激、反應(yīng)、操作性,戰(zhàn)斗節(jié)奏快。而回合制戰(zhàn)斗系統(tǒng)側(cè)重于休閑、戰(zhàn)略、配合,戰(zhàn)斗節(jié)奏慢。早期的電子游戲由于設(shè)備硬件條件有限,大多采用回合制戰(zhàn)斗系統(tǒng)。
隨著科技的發(fā)展和設(shè)備硬件的提升,如今回合制游戲的數(shù)量比例有所下降,但回合制游戲在國內(nèi)游戲市場依舊占據(jù)著想當(dāng)大的份額,仍有大量玩家熱衷這種戰(zhàn)斗模式,幾款眾所周知的國產(chǎn)單機(jī)游戲如《軒轅劍》系列、《仙劍奇?zhèn)b傳》系列、《古劍奇譚》系列以及國內(nèi)在線人數(shù)最多的MMORPG《夢幻西游》均是采用回合制戰(zhàn)斗系統(tǒng)的游戲。
本人也是熱衷于回合制戰(zhàn)斗系統(tǒng)的玩家之一,可縱觀近年來國內(nèi)回合制游戲的發(fā)展,國內(nèi)回合制游戲一直止步不前,《軒轅劍》系列、《仙劍奇?zhèn)b傳》系列、《古劍奇譚》銷量下降,MMORPG《夢幻西游》也有降溫跡象,甚至國內(nèi)大多回合制網(wǎng)游只是復(fù)制在《夢幻西游》或“換皮”,缺少創(chuàng)新和突破。本人希望在研究和實(shí)現(xiàn)回合制戰(zhàn)斗系統(tǒng)的基礎(chǔ)上,能夠找到突破和創(chuàng)新點(diǎn)。同時在游戲編程方面,即時制邏輯較為簡單明了清晰,而回合制則比較繁瑣復(fù)雜,而且在Unity引擎上實(shí)現(xiàn)回合制戰(zhàn)斗系統(tǒng)的相關(guān)資料較少。綜上原因,本人撰寫本文,希望能對志同道合者有所啟發(fā),同時也尋求學(xué)術(shù)交流。
項目將在2017年6月開源,開源地址
/share/home?uk=1017424337
By江正覬
2016.6
第1章緒論
1.1回合制游戲簡介
1.1.1廣義上的回合制游戲
凡“我方與敵方在單個回合內(nèi)輪流行動,只有輪到我方(自己)的回合或者是新的回合開始時,才可進(jìn)行行動”的游戲,都可歸類為廣義上的回合制游戲,而且絕大大多數(shù)情況下,單個回合內(nèi)敵我雙方行動次數(shù)相同。從廣義上來說,回合制游戲范圍非常廣,棋牌、卡牌、戰(zhàn)棋策略、回合制戰(zhàn)斗模式都能歸為此類。
1.1.2狹義上的回合制游戲
狹義上的回合制游戲,是從廣義回合制游戲中細(xì)分,特指回合制戰(zhàn)斗模式的游戲,與即時制戰(zhàn)斗模式相對。
1.2回合制戰(zhàn)斗系統(tǒng)簡介
在回合制戰(zhàn)斗模式下,每個回合開始時,敵我雙方各自為雙方戰(zhàn)斗角色下達(dá)戰(zhàn)斗指令,待雙方所有角色下達(dá)完戰(zhàn)斗指令或超過時限(回合制網(wǎng)絡(luò)游戲均會設(shè)置下達(dá)戰(zhàn)斗指令的時間限制)后雙方所有角色開始行動,一般根據(jù)角色自身“速度(敏捷)”的屬性數(shù)值輪流行動,期間若果某一方符合戰(zhàn)敗條件(某方全體陣亡或全體人物陣亡)則戰(zhàn)斗結(jié)束,如所有角色行動完后敵我雙方均沒符合戰(zhàn)敗條件,則進(jìn)入下回合,如此循環(huán)。
1.3實(shí)踐項目《PKer》簡介
《PKer》是一個以回合制競技和社交為賣點(diǎn)的PC和移動端跨平臺網(wǎng)絡(luò)游戲,是游戲與社交APP的融合體。游戲主要玩法是玩家與玩家之間的回合制戰(zhàn)斗PK。
通過移動設(shè)備GPS定位功能(PC端無法使用),能夠快速搜索在你身邊的游戲房間和玩家,與其開展戰(zhàn)斗。
游戲提供一定數(shù)量的基礎(chǔ)裝備和寵物讓玩家任意領(lǐng)取,故玩家可以隨時更換裝備和寵物,新玩家也能以此為基礎(chǔ)投入到戰(zhàn)斗中。更強(qiáng)的裝備和稀有的寵物通過合成、付費(fèi)租用等渠道獲得。角色的屬性和職業(yè)也可以隨時更改,以便隨時改變戰(zhàn)術(shù)和改變在隊伍里中的定位。
第2章開發(fā)環(huán)境和部分涉及技術(shù)簡介
2.1開發(fā)環(huán)境簡介
本文實(shí)踐項目的服務(wù)器采用國內(nèi)IOCP開源框架“HP-Socket”,并且連接到Mysql數(shù)據(jù)庫,客戶端采用近年比較火熱的強(qiáng)大跨平臺引擎Unity3D(2D,C#)并且使用Sqlite作為嵌入式數(shù)據(jù)庫。
2.2Unity協(xié)同程序
2.2.1Unity協(xié)同程序簡介
協(xié)同程序(Coroutine),通常簡稱“協(xié)程”,顧名思義,是一段協(xié)助的程序(方法),很多人以為它是另開一個線程執(zhí)行一段程序,其不然,實(shí)際上它是從主線程每幀或每隔一定時間調(diào)用的程序。當(dāng)協(xié)程創(chuàng)建后,主線程中創(chuàng)建協(xié)程的語句后面的代碼塊會“掛起”,直到協(xié)同程序結(jié)束后,才會繼續(xù)執(zhí)行創(chuàng)建協(xié)程語句后面的代碼。當(dāng)協(xié)程中的代碼執(zhí)行完或者使用yieldbreak語句時,協(xié)程才會結(jié)束,并且返回到主線程中的創(chuàng)建該協(xié)程的語句的位置,繼續(xù)執(zhí)行后面的代碼。協(xié)程中使用yieldreturn幀數(shù)/newWaitForSeconds(秒數(shù))語句可以實(shí)現(xiàn)隔多少幀或多少秒后再執(zhí)行后續(xù)代碼。另外協(xié)程可以嵌套協(xié)程,利用協(xié)程的特點(diǎn)和嵌套,可以實(shí)現(xiàn)很多復(fù)雜和有趣的功能,十分強(qiáng)大。
2.2.2Unity協(xié)同程序的運(yùn)用
協(xié)程廣泛地運(yùn)用在計時、延遲、控制物體運(yùn)動、等待物體狀態(tài)的改變、有順序地讓物體執(zhí)行一系列動作等方面上。
根據(jù)協(xié)程的特點(diǎn),協(xié)程中可以使用“循環(huán)+條件判斷+yieldreturn幀數(shù)/newWaitForSeconds(秒數(shù))”實(shí)現(xiàn)每隔多少幀或者多少秒后再次執(zhí)行條件判斷語句,當(dāng)判斷語句滿足跳出循環(huán),從而讓協(xié)程代碼執(zhí)行完結(jié)束,回到主線程繼續(xù)執(zhí)行后續(xù)代碼,利用此功能,可以很方便地實(shí)現(xiàn)某物體達(dá)到某狀態(tài)后再執(zhí)行程序。
示例代碼:
主線程代碼
StartCoroutine(actor.Move(getAttackPosition(nTargetIndex)));
Inti=0;
協(xié)同程序Move方法
publicIEnumeratorMove(Vector3destPos)
{
while(transform.localPosition!=destPos)
{
transform.localPosition=Vector3.MoveTowards(transform.localPosition,destPos,GlobalData.BATTLE_SPRITE_MOVE_SPEED*Time.deltaTime);
yieldreturn0;
}
}
上述代碼中,主線程StartCoroutine方法創(chuàng)建一個協(xié)程Move,待協(xié)程Move執(zhí)行完成返回后,主線程才執(zhí)行i=0語句??墒菂f(xié)程Move的返回條件有點(diǎn)特殊,yieldreturn0語句表示協(xié)程運(yùn)行到此處掛起,等下一幀再從本語句繼續(xù)運(yùn)行,由于yieldreturn0在while循環(huán)內(nèi),所以不管yieldreturn0多少次,都依然在while循環(huán)內(nèi),而且while循環(huán)每一幀循環(huán)一次。直到while不滿足循環(huán)條件(即transform.localPosition==destPos),則協(xié)程能夠完成使命執(zhí)行完成并返回。可以猜測到,所控制的物體可能通過Update方法或者其他方法每幀在移動,直到移動到目標(biāo)地點(diǎn),才執(zhí)行主線程后面的代碼。
2.3單例設(shè)計模式
2.3.1單例設(shè)計模式
單例設(shè)計模式是常見和簡單的一種軟件設(shè)計模式,單例模式下的類能確保在整個工程項目中只允許存在最多一個實(shí)例對象。單例模式下的類通常不能直接通過構(gòu)造函數(shù)new出一個實(shí)例,而且構(gòu)造函數(shù)通常會設(shè)置成私有,外部不可訪問。只有通過類的一個靜態(tài)方法可以創(chuàng)建或獲取有且只有唯一一個的對象實(shí)例。
2.3.2單例設(shè)計模式的運(yùn)用
單例設(shè)計模式下的類往往具有通用性或全局性,用于保存全局?jǐn)?shù)據(jù),需要訪問其變量的外部類只需要通過單例類的靜態(tài)方法即可獲得其唯一的實(shí)例,從而訪問其內(nèi)部變量。
示例代碼:
publicclassClientSocket//單例類ClientSocket
{
privatestaticClientSocket_client_socket;//保存本類的唯一實(shí)例
privatestaticMessageManager_msg_mgr;
privatestaticSocket_socket;
privatestring_web="";
privateIPAddress_ip;
privateint_port=8000;
privatebyte[]_buf=newbyte[1024];
privateCircularBuffer_circularBuf=newCircularBuffer(4096);
privateClientSocket(){
}
publicstaticClientSocketgetInstance()
{
if(_client_socket==null)//若實(shí)例不存在則創(chuàng)建,實(shí)例已存在則直接返回
{
_client_socket=newClientSocket();
_msg_mgr=MessageManager.getInstance();
}
return_client_socket;
}
……
}
2.3.3單例設(shè)計模式在Unity中的運(yùn)用
在Unity中使用單例設(shè)計模式,有時會有額外的意義。在Unity中,通常一個類會作為一個組件掛載到一個物體上,可是如果進(jìn)行了場景切換,當(dāng)前場景所有物體以及物體所掛載的所有組件都會被銷毀,這時如果想要所有場景都能訪問一個類的實(shí)例以及其變量,則需要把該類設(shè)置成單例類,并且不能繼承MonoBehaviour,而且不能掛載到任何一個物體上,這樣就可以保證整個游戲中不管場景怎么切換,該類的實(shí)例一直存在,而且只有唯一一個實(shí)例,所有場景均可通過靜態(tài)方法獲取實(shí)例并且訪問。
2.4分包算法
2.4.1分包的原因
TCP在發(fā)送消息時,如果發(fā)送間隔太短,發(fā)送方有可能出現(xiàn)一次發(fā)送多個消息的情況,而接收方便會一次接收到多個消息,另外,很多時候網(wǎng)絡(luò)情況較差或不穩(wěn)定,接收方遲遲收不到消息,過一段時間有可能一次過接收到此前該接收的多個消息,這些現(xiàn)象就是粘包。
由于粘包現(xiàn)象的存在,如果不進(jìn)行分包,接收方可能只能讀取到粘包數(shù)據(jù)的頭一個消息,后面的消息將會丟失,甚至影響后續(xù)接收的消息,嚴(yán)重影響程序的運(yùn)行。因此,我們需要一個分包算法來檢測粘包情況并進(jìn)行分包,以便正確讀取所有來自發(fā)送方的消息。
2.4.2環(huán)形緩沖區(qū)(CircularBuffer)
在分包算法中,我們需要用到一個數(shù)據(jù)結(jié)構(gòu)——環(huán)形緩沖區(qū)。之所以要用到環(huán)形緩沖區(qū),是因?yàn)榉职拔覀円呀邮盏降乃袛?shù)據(jù)存放在一個緩沖區(qū)中,分包時根據(jù)消息的長度從緩沖區(qū)里取數(shù)據(jù),取出后緩沖區(qū)相應(yīng)地移除對應(yīng)的數(shù)據(jù),這樣反復(fù)頻繁進(jìn)行添加和刪除操作如果只用普通的緩沖區(qū)(byte數(shù)組/char數(shù)組)的話,則要頻繁地移動數(shù)據(jù)存放的位置,十分影響程序運(yùn)行效率,為此需要引入環(huán)形緩沖區(qū)。
下面是環(huán)形緩沖區(qū)(CricularBuffer)類的UML類圖(C++):
圖2-1環(huán)形緩沖區(qū)UML類圖
說明:
buf:指向緩沖區(qū)的指針
front:緩沖區(qū)的數(shù)據(jù)的起始位置
rear:緩沖區(qū)的數(shù)據(jù)的尾部位置
lock:用于多線程同步的臨界區(qū),防止多個線程訪問修改緩沖區(qū)數(shù)據(jù)
size:緩沖區(qū)數(shù)據(jù)的長度
capacity:緩沖區(qū)的容量
CircularBuffer:構(gòu)造函數(shù),創(chuàng)建一個指定容量為參數(shù)大小的緩沖區(qū)
~CircularBuffer:析構(gòu)函數(shù),釋放緩沖區(qū)
clear:清空緩沖區(qū)
pushBuf:往緩沖區(qū)尾部添加數(shù)據(jù)
popBuf:從緩沖區(qū)頭部得到數(shù)據(jù),并且緩沖區(qū)移除相應(yīng)數(shù)據(jù)
getBuf:從緩沖區(qū)頭部得到數(shù)據(jù),但緩沖區(qū)不移除數(shù)據(jù)
isEmpty:判斷緩沖區(qū)是否為空
由于環(huán)形緩沖區(qū)使用front起始位置和rear尾部位置記錄數(shù)據(jù)存放的位置,添加或移除數(shù)據(jù)不需要移動數(shù)據(jù)的儲存位置,運(yùn)行效率高。
2.4.3分包算法流程圖
圖2-2分包算法流程圖
說明:
定義或獲得一個容量足夠大的環(huán)形緩沖區(qū)(具體大小請根據(jù)實(shí)際情況考慮);
接收到數(shù)據(jù)后,往環(huán)形緩沖區(qū)尾部添加數(shù)據(jù);
判斷緩沖區(qū)的數(shù)據(jù)長度是否大于等于4(消息頭的長度),本文實(shí)踐項目的結(jié)構(gòu)體消息頭由消息類型(ushort)和消息長度(ushort)組成,共4字節(jié)。若緩沖區(qū)數(shù)據(jù)長度小于消息頭長度,則無法獲取第一條消息的長度,也無法分包,也表明數(shù)據(jù)接收不全,回到(2)繼續(xù)接收數(shù)據(jù),不進(jìn)行任何操作;若緩沖區(qū)數(shù)據(jù)長度大于等于消息頭長度,則開始進(jìn)行分包;
從緩沖區(qū)頭部getBuf獲得4字節(jié)數(shù)據(jù)(消息頭),不改變緩沖區(qū)數(shù)據(jù),從消息頭得到第一包消息的長度;
判斷緩沖區(qū)數(shù)據(jù)長度,若緩沖區(qū)數(shù)據(jù)長度大于第一包消息的長度,則第一包消息接收完并可取,根據(jù)第一包消息的長度popBuf得到第一包消息數(shù)據(jù),并且緩沖區(qū)移除相應(yīng)數(shù)據(jù),處理該消息;若緩沖區(qū)數(shù)據(jù)長度小于第一包消息長度(此時緩沖區(qū)數(shù)據(jù)長度大于等于4,但是小于第一包消息的長度),則說明第一包消息還沒接收完,回到(2)繼續(xù)接收,不進(jìn)行任何操作;
回到(4),一直循環(huán)。
第3章戰(zhàn)斗動畫實(shí)現(xiàn)方案的研究與對比
3.1研究背景
筆者認(rèn)為回合制戰(zhàn)斗系統(tǒng)實(shí)現(xiàn)的最大難點(diǎn),那無疑就是客戶端戰(zhàn)斗動畫的實(shí)現(xiàn)?;睾现茟?zhàn)斗系統(tǒng)的戰(zhàn)斗動畫,不是平常我們說的“動畫”,它是由數(shù)據(jù)轉(zhuǎn)換過來的動態(tài)動畫,動畫內(nèi)容由數(shù)據(jù)決定。例如動畫數(shù)據(jù)是“某個角色攻擊某個角色”,動畫內(nèi)容便是“攻擊者移動到目標(biāo)面前并播放攻擊動作動畫,目標(biāo)播放受傷動作動畫,顯示扣血,攻擊者返回到本來的位置”;再例如動畫數(shù)據(jù)是“某個角色使用技能攻擊某個角色”,動畫內(nèi)容便是“施法者播放施法動作動畫,然后在目標(biāo)身上播放技能特效,等到特效播放到某一幀,目標(biāo)播放受傷動作動畫,顯示扣血”。
上述例子已經(jīng)是回合制戰(zhàn)斗系統(tǒng)最基本的戰(zhàn)斗動畫,更不用說多次攻擊或者多次施法,可謂難上加難。更何況,戰(zhàn)斗動畫的質(zhì)量極大影響回合制游戲的可玩性,而且回合制戰(zhàn)斗除了玩家下達(dá)戰(zhàn)斗指令外,其余時間全部都在播放戰(zhàn)斗動畫上。
所以,筆者認(rèn)為客戶端的戰(zhàn)斗動畫實(shí)現(xiàn)是整個回合制戰(zhàn)斗系統(tǒng)的重點(diǎn)和難點(diǎn),為了正確謹(jǐn)慎地抉擇實(shí)現(xiàn)方案,少走彎路,額外對戰(zhàn)斗動畫的實(shí)現(xiàn)展開了研究。
3.2實(shí)現(xiàn)方案一:有限狀態(tài)機(jī)
這是筆者最先想到的方案,畢竟有限狀態(tài)機(jī)在游戲編程中實(shí)在極為常用,相信不少讀者也會率先聯(lián)想到這種方式。
有限狀態(tài)機(jī)代碼示例:
voidUpdate(){
switch(state)
{
case(int)State.Standby:
……
break;
case(int)State.Attack:
……
break;
case(int)State.Magic:
……
break;
……
}
……
}
有限狀態(tài)機(jī)方案下,Update方法每幀檢測記錄狀態(tài)的變量state,從而決定究竟要執(zhí)行何種行為,當(dāng)行為執(zhí)行完或者某個事件觸發(fā)時,通過修改狀態(tài)變量state,改變執(zhí)行的行為。
優(yōu)點(diǎn):
(1)靈活可變,隨時隨地都可以改變狀態(tài),從而改變執(zhí)行的行為
缺點(diǎn):
每幀都需要檢測狀態(tài)變量,影響程序運(yùn)行效率;
如果要實(shí)現(xiàn)一系列復(fù)雜的行為,代碼量大而且凌亂,邏輯復(fù)雜,例如要實(shí)現(xiàn)“攻擊者移動到目標(biāo)面前,攻擊者播放攻擊動畫,目標(biāo)播放受傷動畫,顯示扣血,攻擊者返回原本位置”這樣的功能,可能需要不止一個狀態(tài)機(jī);
Update方法變得臃腫,很多時候Update還需要做其他事情;
3.3實(shí)現(xiàn)方案二:協(xié)同程序(Coroutine)
在感覺方案一可行性不高的情況下,本人開始尋求其他實(shí)現(xiàn)方案,直到發(fā)現(xiàn)協(xié)同程序(Coroutine)。若讀者不了解協(xié)程可閱本文第二章,協(xié)同程序在本文第2章有簡略介紹,此處不再作介紹。個人感覺Unity的協(xié)同程序跟Cocos2d的CCSequence動作有點(diǎn)像,都能很方便實(shí)現(xiàn)按順序執(zhí)行一系列動作,而且協(xié)同程序比CCSequence更靈活。
協(xié)同程序示例代碼:
IEnumeratorAttack(BATTLE_ANIMbattleAnim)
{
BattleSpritesprite=battleSprites[battleAnim.nActorIndex-1];
yieldreturnStartCoroutine(sprite.Move(getAttackPosition(nTargetIndex)));
yieldreturnStartCoroutine(sprite.AttackAnim());
yieldreturnStartCoroutine(sprite.Back(actor.vOrigPos));
}
協(xié)程Attack()能夠簡單清晰實(shí)現(xiàn)“控制某個物體移動到某個地點(diǎn),完成后進(jìn)行攻擊,攻擊完成后返回到某個地點(diǎn)”,一步完成之后再進(jìn)行下一步。
優(yōu)點(diǎn):
不需要在Update每幀調(diào)用,協(xié)程開啟后根據(jù)代碼邏輯等待(每)n幀/n秒自動調(diào)用;
代碼邏輯清晰
能夠很好實(shí)現(xiàn)按順序執(zhí)行一系列復(fù)雜的行為
缺點(diǎn):
如要中途終止協(xié)程,有一定的終止條件
沒狀態(tài)機(jī)靈活,難以臨時轉(zhuǎn)變行為
3.4方案抉擇結(jié)論
顯而易見,經(jīng)過筆者的研究和深思熟慮,本文采用了協(xié)同程序方案。理由很簡單,回合制戰(zhàn)斗動畫幾乎全避開了協(xié)程的缺點(diǎn),體現(xiàn)了協(xié)程的優(yōu)點(diǎn)。因?yàn)榛睾现茟?zhàn)斗動畫是由服務(wù)器發(fā)來的動畫數(shù)據(jù)轉(zhuǎn)換的,數(shù)據(jù)自始至終沒有改變,客戶端只負(fù)責(zé)播放動畫效果,并沒有修改數(shù)據(jù),那么從數(shù)據(jù)轉(zhuǎn)化為動畫那刻開始,動畫就不可能有變化或者中途終止,并不需要程序的靈活性。這么看來,協(xié)程用在回合制戰(zhàn)斗動畫的播放很是適合。
另外,讀者也可考慮行為樹方案,由于筆者時間和能力有限,截至目前未能深入學(xué)習(xí)研究行為樹,不知是否能比協(xié)程更好地實(shí)現(xiàn)戰(zhàn)斗動畫,所以本文未能提及,懇請體諒。
第4章回合制網(wǎng)游戰(zhàn)斗系統(tǒng)設(shè)計
4.1回合制網(wǎng)游戰(zhàn)斗系統(tǒng)設(shè)計
我們從回合制網(wǎng)游中不難發(fā)現(xiàn),在客戶端面前,我們可以看到一場回合制戰(zhàn)斗可劃分為以下階段:進(jìn)入戰(zhàn)斗-玩家下達(dá)戰(zhàn)斗指令(很多情況下需要下達(dá)人物和寵物兩個戰(zhàn)斗指令)-戰(zhàn)斗動畫-戰(zhàn)斗結(jié)束。經(jīng)過本人對上述戰(zhàn)斗過程的研究、思考和分析,得出個人的回合制戰(zhàn)斗系統(tǒng)實(shí)現(xiàn)思路,戰(zhàn)斗系統(tǒng)流程圖如圖:
圖4-1回合制網(wǎng)游戰(zhàn)斗系統(tǒng)流程圖
4.2回合制網(wǎng)游戰(zhàn)斗系統(tǒng)服務(wù)器實(shí)現(xiàn)思路
(1)戰(zhàn)斗開始發(fā)送“戰(zhàn)斗初始化消息”給客戶端,“戰(zhàn)斗初始化消息”包含所有戰(zhàn)斗角色(人物和寵物)的名字、圖形及動畫控制器ID、最大Hp、當(dāng)前Hp、最大Mp、當(dāng)前Mp等數(shù)據(jù),客戶端只關(guān)心需要顯示的內(nèi)容;
(2)根據(jù)戰(zhàn)斗角色的數(shù)量,等待接收并保存數(shù)量與角色數(shù)量想當(dāng)?shù)膩碜钥蛻舳说摹皯?zhàn)斗指令消息”,即等待所有戰(zhàn)斗角色都下達(dá)完戰(zhàn)斗指令;
(3)接收到足夠數(shù)量的“角色戰(zhàn)斗指令消息”后,根據(jù)角色的“速度”屬性數(shù)值,倒序(即速度高者先行動)處理每一個戰(zhàn)斗指令所造成的影響,并更新服務(wù)器各個角色的數(shù)值,發(fā)送對應(yīng)的“動畫消息”給所有客戶端,每處理一個“戰(zhàn)斗指令消息”就發(fā)送一個對應(yīng)的“動畫消息”;
(4)待所有“戰(zhàn)斗指令消息”處理完并發(fā)送完對應(yīng)的“動畫消息”后,發(fā)送“動畫播放消息”;
(5)判斷雙方角色的陣亡情況,若一方符合戰(zhàn)敗條件(所有角色陣亡或者所有人物陣亡,具體根據(jù)游戲設(shè)定決定)則結(jié)束戰(zhàn)斗,否則回到步驟(2)進(jìn)入下一個回合,如此循環(huán)。
4.3回合制網(wǎng)游戰(zhàn)斗系統(tǒng)客戶端實(shí)現(xiàn)思路
(1)若接收到“戰(zhàn)斗初始化消息”,則進(jìn)入戰(zhàn)斗,并根據(jù)消息里的數(shù)據(jù),初始化每一個戰(zhàn)斗角色;
(2)顯示人物戰(zhàn)斗指令菜單,根據(jù)玩家的操作,發(fā)送“戰(zhàn)斗指令消息”,人物戰(zhàn)斗指令菜單消失;
(3)若沒有參戰(zhàn)寵物,直接跳到下一步,若有參戰(zhàn)寵物,顯示寵物戰(zhàn)斗指令菜單,根據(jù)玩家的操作,發(fā)送“戰(zhàn)斗指令消息”,寵物戰(zhàn)斗指令菜單消失;
(4)接收并保存每一個來自服務(wù)器的“動畫消息”或“動畫播放消息”;
(5)收到“動畫播放消息”后,讀取并處理每一個“動畫消息”,轉(zhuǎn)化為對應(yīng)等量的戰(zhàn)斗動畫類并用容器保存,遍歷容器播放所有動畫;
(6)當(dāng)前回合所有戰(zhàn)斗動畫播放完后,判斷雙方陣亡情況,若一方符合戰(zhàn)敗條件(所有角色陣亡或者所有人物陣亡,具體根據(jù)游戲設(shè)定決定)則結(jié)束戰(zhàn)斗,否則回到步驟(2)進(jìn)入下一個回合,如此循環(huán)。
4.4戰(zhàn)斗系統(tǒng)框架結(jié)構(gòu)(以實(shí)踐項目《PKer》為例)
雖然本文主要闡述戰(zhàn)斗系統(tǒng),但是由于戰(zhàn)斗系統(tǒng)較為復(fù)雜,為了讓讀者更好的理解本文所述戰(zhàn)斗系統(tǒng)的實(shí)現(xiàn)思路,以實(shí)踐項目《PKer》為例,對游戲的戰(zhàn)斗系統(tǒng)架構(gòu)和相關(guān)功能架構(gòu)進(jìn)行簡單的羅列和說明。
圖4-2實(shí)踐項目《PKer》戰(zhàn)斗系統(tǒng)及相關(guān)功能架構(gòu)
說明:
玩家從游戲大廳可以搜索加入房間或創(chuàng)建房間,與房間內(nèi)其他玩家進(jìn)行對戰(zhàn)進(jìn)入戰(zhàn)斗(讀者可根據(jù)自身游戲玩法考慮如何觸發(fā)戰(zhàn)斗,如常見的回合制游戲通過暗雷或明雷遇敵、玩家對點(diǎn)觸發(fā)戰(zhàn)斗);
《PKer》中玩家可以直接在玩家屬性配置界面中通過點(diǎn)選“寵物庫”內(nèi)的寵物即可獲得對應(yīng)寵物,并且通過設(shè)置“參戰(zhàn)寵物”可讓寵物在戰(zhàn)斗中出戰(zhàn)(讀者可根據(jù)自身游戲玩法考慮寵物的獲得途徑,常見的途徑有戰(zhàn)斗捕捉、任務(wù)獎勵等);
《PKer》中玩家可以直接在玩家屬性配置界面中通過點(diǎn)選“裝備物品庫”內(nèi)的裝備/物品即可獲得對應(yīng)裝備/物品,裝上裝備將提高角色的屬性使角色更具戰(zhàn)斗力,放在物品欄的物品可以在戰(zhàn)斗中使用回復(fù)Hp/Mp(讀者可根據(jù)自身游戲玩法考慮裝備物品的獲得途徑,常見的途徑有戰(zhàn)斗獎勵、任務(wù)獎勵等);
《PKer》中玩家可以直接在玩家屬性配置界面中更改職業(yè),從而獲得在戰(zhàn)斗中使用的技能;
進(jìn)入戰(zhàn)斗后,參戰(zhàn)角色的屬性由各個玩家配置(屬性加點(diǎn)、裝備、參戰(zhàn)寵物、職業(yè)等)所決定;
各玩家通過指令菜單下達(dá)指令從而控制自身角色和自身參戰(zhàn)寵物(如有設(shè)置參戰(zhàn)寵物)的行動。其中,使用技能能夠選擇使用自身職業(yè)的技能,使用物品能夠選擇使用物品欄的物品;
戰(zhàn)斗動畫主要由多個協(xié)同程序組成來實(shí)現(xiàn),根據(jù)各個參戰(zhàn)人物/寵物的下達(dá)的戰(zhàn)斗指令對應(yīng)的播放其行為的動畫,不同的行為動畫內(nèi)容不一樣;
而在技能動畫中,為了增加回合制戰(zhàn)斗的畫面感和可玩性,對不同的技能配置了不同的特效播放方式,讓特效動畫更華麗更多元化,詳細(xì)實(shí)現(xiàn)方式在本文5.3.6和5.3.7小節(jié)有闡述;
第5章回合制戰(zhàn)斗系統(tǒng)實(shí)現(xiàn)
5.1戰(zhàn)斗系統(tǒng)相關(guān)消息結(jié)構(gòu)體的定義
結(jié)構(gòu)體消息是服務(wù)器與客戶端溝通的“共同語言”,結(jié)構(gòu)體消息在客戶端和服務(wù)器分別定義并且數(shù)據(jù)結(jié)構(gòu)是相同,發(fā)送方填寫結(jié)構(gòu)體數(shù)據(jù),接收方先獲取消息頭的消息類型ID和長度,再判斷是哪種類型的消息并轉(zhuǎn)換成該類型結(jié)構(gòu)體,然后讀取內(nèi)容并進(jìn)行對應(yīng)的處理。
以下是Unity客戶端(C#)中定義的相關(guān)結(jié)構(gòu)體消息,服務(wù)器的定義與其一致,但由于服務(wù)器(C++)與客戶端(C#)的編程語言不同所以定義語法有些許區(qū)別。
//戰(zhàn)斗初始化消息
publicstructMSG_BATTLE_INIT
{
publicushortnMsgID;//消息類型ID
publicushortnLen;//結(jié)構(gòu)體長度
publicuintnBattleID;//戰(zhàn)局ID
[MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]
publicBATTLE_SPRITE_INIT[]battleSprites;//所有戰(zhàn)斗角色基本數(shù)據(jù)
};
//戰(zhàn)斗角色(人物/寵物)基本數(shù)據(jù)消息
publicstructBATTLE_SPRITE_INIT
{
publicuintnID;//玩家/寵物ID(客戶端用此值判斷是否有戰(zhàn)斗成員,可能還會用來標(biāo)識自身和自身寵物)
[MarshalAs(UnmanagedType.ByValArray,SizeConst=22)]
publicbyte[]strName;//戰(zhàn)斗人物/寵物名字
publicuintnImageID;//圖形及動畫控制器ID
publicshortnHpMax;//最大HP
publicshortnHp;//當(dāng)前HP
publicshortnMpMax;//最大MP
publicshortnMp;//當(dāng)前MP
};
//戰(zhàn)斗指令消息
publicstructMSG_BATTLE_COMMAND
{
publicushortnMsgID;//消息類型ID
publicushortnLen;//結(jié)構(gòu)體長度
publicushortnActorType;//行動者類型(1=人物2=寵物,由服務(wù)端賦值,客戶端不需要賦值)
publicushortnActorIndex;//行動者索引(由服務(wù)端賦值,客戶端不需要賦值)
publicushortnActionType;//行動的類型
publicushortnTargetIndex;//目標(biāo)索引
publicushortnParam;//參數(shù)(根據(jù)行動類型而定,如使用技能則是技能ID,使用物品則是物品欄位置,切換戰(zhàn)寵則是寵物欄位置)
};
//戰(zhàn)斗動畫播放消息(客戶端收到此消息后開始播放戰(zhàn)斗動畫)
publicstructMSG_BATTLE_ANIM_BEGIN
{
publicushortnMsgID;//消息類型ID
publicushortnLen;//結(jié)構(gòu)體長度
};
//戰(zhàn)斗動畫消息
publicstructMSG_BATTLE_ANIM
{
publicushortnMsgID;//消息類型ID
publicushortnLen;//結(jié)構(gòu)體長度
publicushortnActorIndex;//行動者索引
[MarshalAs(UnmanagedType.ByValArray,SizeConst=10)]
publicushort[]nTargetIndex;//目標(biāo)索引(初始值為0,0則無目標(biāo))
publicushortaction_type;//行動類型
publicushortnParam;//參數(shù)(根據(jù)行動類型而定,如使用技能則是技能ID,使用物品則是物品欄位置)
[MarshalAs(UnmanagedType.ByValArray,SizeConst=10)]
publicshort[]nActorHp;//行動者Hp影響(<0:扣血,>0:加血,0=無任何影響)
[MarshalAs(UnmanagedType.ByValArray,SizeConst=10)]
publicshort[]nActorMp;//行動者M(jìn)p影響
[MarshalAs(UnmanagedType.ByValArray,SizeConst=10)]
publicshort[]nTargetHp;//目標(biāo)Hp影響(<0:扣血,>0:加血,0=無任何影響)
[MarshalAs(UnmanagedType.ByValArray,SizeConst=10)]
publicshort[]nTargetMp;//目標(biāo)Mp影響
};
5.2服務(wù)器戰(zhàn)斗系統(tǒng)的實(shí)現(xiàn)
5.2.1服務(wù)器戰(zhàn)斗系統(tǒng)相關(guān)結(jié)構(gòu)體
圖5-1服務(wù)器戰(zhàn)斗系統(tǒng)的相關(guān)結(jié)構(gòu)體的關(guān)系圖
//戰(zhàn)局結(jié)構(gòu)體
structBATTLE
{
UINTnBattleID;//戰(zhàn)局ID
BATTLE_SPRITEbattleSprites[20];//戰(zhàn)斗角色(人物/寵物)數(shù)組
std::list<USHORT>team1_survivors_index;//隊伍1存活者索引list
std::list<USHORT>team2_survivors_index;//隊伍2存活者索引list
USHORTnSpriteTotal;//參戰(zhàn)角色總數(shù)
std::multimap<float,MSG_BATTLE_COMMAND*>m_CommandMap;//玩家戰(zhàn)斗指令字典,用于保存每回合接收的戰(zhàn)斗指令消息,Key為角色速度數(shù)值
}
說明:
battleSprites數(shù)組的索引0-4位置分別為隊伍1人物1、隊伍1人物2……,索引5-9位置分別為隊伍1人物1的寵物、隊伍1人物2的寵物……,類似的,索引10-14為隊伍2人物,索引15-19為隊伍2寵物,人物索引+5即該人物的寵物的索引,根據(jù)人物索引即可獲得其寵物索引
//戰(zhàn)斗角色(人物/寵物)
structBATTLE_SPRITE
{
BATTLE_SPRITE_DATA*pBattleData;//戰(zhàn)斗數(shù)據(jù)(包含Hp、Mp、攻擊力等)
CLIENT_DATA*pClient;//客戶端數(shù)據(jù)(CLIENT_DATA包含客戶端IOCP完成鍵、套接字、玩家游戲數(shù)據(jù)等數(shù)據(jù),本文不闡述,請讀者根據(jù)自身游戲服務(wù)器架構(gòu)設(shè)計)
USHORTnType;//角色類型,1=人,2=寵物
USHORTbCommand;//是否已經(jīng)下命令,0=沒下命令,1=已下命令
}
//戰(zhàn)斗數(shù)據(jù)(人物與寵物通用)
structBATTLE_SPRITE_DATA
{
UINTnID;//玩家/寵物ID
charstrName[22];//戰(zhàn)斗人物/寵物名字
UINTnImageID;//圖形及動畫控制器ID
USHORTnLevel;//等級
shortnHpMax;//最大Hp
shortnHp;//當(dāng)前Hp
shortnMpMax;//最大Mp
shortnMp;//當(dāng)前Mp
shortnAtk;//物理攻擊力
shortnDef;//物理防御力
shortnMat;//魔法攻擊力
shortnMdf;//魔法防御力
shortnSpd;//速度
}
5.2.2初始化一個戰(zhàn)局
即初始化一個戰(zhàn)局BATTLE實(shí)例,并根據(jù)參戰(zhàn)玩家的數(shù)據(jù)對戰(zhàn)局所有成員進(jìn)行賦值,由于成員較多,并且游戲邏輯復(fù)雜,讀者可根據(jù)自身游戲邏輯賦值,此處初始化的方式不影響后續(xù)的實(shí)現(xiàn),所以這里不進(jìn)行詳細(xì)闡述,最后在客戶端數(shù)據(jù)存放指向戰(zhàn)局的指針,以便后面通過完成鍵以及客戶端數(shù)據(jù)能夠獲得戰(zhàn)局?jǐn)?shù)據(jù)。
本文假設(shè)一個戰(zhàn)局最多能5位玩家對戰(zhàn)5位玩家,包括每位玩家可出戰(zhàn)的一個戰(zhàn)斗寵物,所以一個戰(zhàn)局最多能有20個戰(zhàn)斗角色,故battleSprites戰(zhàn)斗角色數(shù)組長度為20,讀者可根據(jù)自身游戲邏輯進(jìn)行變更。另外,如果戰(zhàn)局不足20個戰(zhàn)斗角色,本文通過檢查battleSprites中的戰(zhàn)斗數(shù)據(jù)pBattleData是否為NULL進(jìn)行判斷并計數(shù),用成員nSpriteTotal保存戰(zhàn)斗角色總數(shù)。戰(zhàn)局初始時所有戰(zhàn)斗角色理應(yīng)是存活的,battleSprites中所有存在的戰(zhàn)斗角色的索引相應(yīng)的存放到隊伍1存活索引list或隊伍2存活索引list中,本文假設(shè)索引0-9為隊伍1(0-4隊伍1人物,5-9隊伍1寵物),10-19為隊伍2(10-14為隊伍2人物,15-19為隊伍2寵物),并且人物和其寵物的索引相差5(即0索引上的人物其寵物索引為5,如此類推)。
5.2.3接收客戶端的戰(zhàn)斗指令消息
圖5-2接收戰(zhàn)斗指令消息流程圖
收到客戶端發(fā)來的消息后,通過消息頭和消息類型ID(可用宏定義或定義枚舉類型)的判斷,確定是否為戰(zhàn)斗指令消息后,然后處理戰(zhàn)斗指令消息。
本文實(shí)踐項目從IOCP完成鍵可以獲取玩家數(shù)據(jù)進(jìn)而獲取玩家所在的戰(zhàn)局指針(BATTLE*)。收到戰(zhàn)斗指令消息后,通過消息中的行動者索引nActorIndex從戰(zhàn)局的戰(zhàn)斗角色battleSprites數(shù)組中獲取該角色,根據(jù)該角色的“速度”數(shù)值和戰(zhàn)斗指令消息一并加入到戰(zhàn)斗指令字典m_CommandMap中,以便之后遍歷逐個處理。檢測m_CommandMap的元素個數(shù)是否等于戰(zhàn)斗角色總數(shù)(即檢測是否所有戰(zhàn)斗角色都已下達(dá)戰(zhàn)斗指令,若等于則開始遍歷m_CommandMap處理本回合的所有戰(zhàn)斗指令。
5.2.4處理戰(zhàn)斗指令并發(fā)送動畫消息
圖5-3服務(wù)器處理戰(zhàn)斗指令消息流程圖
當(dāng)本回合所有戰(zhàn)斗角色都下達(dá)戰(zhàn)斗指令(服務(wù)器收到的指令數(shù)等于角色數(shù)量)后,開始倒序遍歷(倒序的原因是,multimap按從小到大排序,而我們的邏輯是速度高的先行動)處理每一條戰(zhàn)斗指令。
倒序遍歷時,先判斷發(fā)出該戰(zhàn)斗指令消息的角色是否已經(jīng)死亡,若死亡則不能進(jìn)行任何行為,直接跳出進(jìn)入下一次循環(huán)。若發(fā)出指令的角色沒有死亡,根據(jù)指令的nActionType行動類型(攻擊、使用技能、使用物品、更換寵物等)進(jìn)行不同的處理,計算每一條戰(zhàn)斗指令所造成的影響,并發(fā)送對應(yīng)的動畫消息。
若在計算完每一條戰(zhàn)斗指令所造成的影響后,檢查雙方存活狀況,若一方全員陣亡則戰(zhàn)斗結(jié)束,并發(fā)送戰(zhàn)斗動畫播放消息,客戶端開始播放動畫。
若計算完所有戰(zhàn)斗指令后戰(zhàn)斗并沒有結(jié)束,發(fā)送戰(zhàn)斗動畫播放消息,客戶端開始播放動畫,進(jìn)入下一回合,清空m_CommandMap所有元素,服務(wù)器繼續(xù)接收新回合的來自客戶端的戰(zhàn)斗指令消息。
下面是不同的行動類型的不同處理方式:
攻擊:
聲明一個戰(zhàn)斗動畫消息,nActionType賦值為“攻擊(枚舉或自定義宏)”,根據(jù)戰(zhàn)斗指令消息里的nActorIndex行動者索引和nTargetIndex目標(biāo)索引從戰(zhàn)局中獲取對應(yīng)的戰(zhàn)斗角色(battleSprites[nActorIndex]和battleSprites[nTargetIndex]),若目標(biāo)死亡則從對應(yīng)隊伍的存活者列表中隨機(jī)一個新目標(biāo)索引。把目標(biāo)索引值賦值給戰(zhàn)斗動畫消息的nTargetIndex[0]。
根據(jù)行動者攻擊和目標(biāo)防御力計算傷害值,賦值給nTargetHp[0],并且目標(biāo)扣除對應(yīng)Hp,判斷目標(biāo)扣除Hp后Hp是否小于等于0(即死亡),若死亡則從對應(yīng)隊伍的存活者列表中移除。
最后,發(fā)送戰(zhàn)斗動畫消息給戰(zhàn)局所有玩家。
使用技能:
本文的實(shí)踐項目通過數(shù)據(jù)庫配置所有技能的相關(guān)數(shù)據(jù),包括技能的ID、作用目標(biāo)數(shù)量、特效動畫ID、特效播放方式(僅在客戶端使用)、Mp消耗、傷害公式等。
聲明一個戰(zhàn)斗動畫消息,nActionType賦值為“使用技能(枚舉或自定義宏)”,通過戰(zhàn)斗指令消息的nParam查找數(shù)據(jù)庫的技能表獲取該技能的相關(guān)數(shù)據(jù),根據(jù)戰(zhàn)斗指令消息的nActorIndex和nTargetIndex從戰(zhàn)局獲得對應(yīng)的角色battleSprites[nActorIndex]和battleSprites[nTargetIndex]),根據(jù)技能Mp消耗數(shù)值賦值到動畫消息的nActorMp上,并且減少使用者角色的Mp。如果目標(biāo)角色死亡,則從目標(biāo)角色的隊伍存活者列表中隨機(jī)得到新的目標(biāo)索引,并賦值多體戰(zhàn)斗動畫消息nTargetIndex數(shù)組的對應(yīng)索引位置上,再根據(jù)行動者的魔法攻擊力和目標(biāo)的魔法防御力以及技能的傷害公式計算傷害數(shù)值,賦值nTargetHp數(shù)組對應(yīng)的索引位置上,并且目標(biāo)扣除對應(yīng)Hp,判斷目標(biāo)扣除Hp后Hp是否小于等于0(即死亡),若死亡則從對應(yīng)隊伍的存活者列表中移除。之后再隨機(jī)目標(biāo),并計算傷害數(shù)值,直到目標(biāo)數(shù)量達(dá)到技能的作用目標(biāo)數(shù)量。
最后,發(fā)送戰(zhàn)斗動畫消息給戰(zhàn)局所有玩家。
使用物品:
本文的實(shí)踐項目通過數(shù)據(jù)庫配置所有物品的相關(guān)數(shù)據(jù),包括物品的ID、作用于單體/全體、Hp回復(fù)量、Mp回復(fù)量等。
聲明一個戰(zhàn)斗動畫消息,nActionType賦值為“使用物品(枚舉或自定義宏)”,通過戰(zhàn)斗指令消息的nParam獲取玩家對應(yīng)物品欄位置的物品ID(物品欄的實(shí)現(xiàn)本文不闡述),把物品ID賦值給戰(zhàn)斗動畫消息的nParam,根據(jù)物品ID查找數(shù)據(jù)庫的物品表獲取該物品的相關(guān)數(shù)據(jù),根據(jù)戰(zhàn)斗指令消息的nActorIndex賦值給動畫消息的nActorIndex,根據(jù)物品是作用于單體還是全體對動畫消息的nTargetIndex數(shù)組進(jìn)行賦值,根據(jù)物品的Hp回復(fù)量和Mp回復(fù)量分別對nTargetHp和nTargetMp數(shù)組進(jìn)行賦值。根據(jù)物品回復(fù)量更新目標(biāo)的Hp/Mp,注意不能超出最大Hp上限/最大Mp上限。
最后,發(fā)送戰(zhàn)斗動畫消息給戰(zhàn)局所有玩家。
5.2.5說明
本文為了盡量簡短地闡述實(shí)現(xiàn)方式,戰(zhàn)斗指令消息的行動者索引nActorIndex由客戶端直接賦值,服務(wù)器并沒有對此進(jìn)行檢查而直接使用。若客戶端并沒有使用自身角色的索引賦值而對nActorIndex進(jìn)行修改作弊,則能夠冒充其他玩家角色下達(dá)戰(zhàn)斗指令,存在隱患,所以戰(zhàn)斗指令消息的nActorIndex應(yīng)該由服務(wù)器賦值并檢查,但由于本文篇幅所限并且考慮到游戲邏輯的復(fù)雜性和不一性,上述實(shí)現(xiàn)方式并沒有過多考慮防范客戶端作弊,懇請讀者體諒。
而實(shí)際上,服務(wù)器在很多地方都應(yīng)該對客戶端發(fā)來的消息進(jìn)行合法性檢查,防范客戶端外掛或作弊,還請讀者根據(jù)自身游戲邏輯另外考慮。
5.3客戶端戰(zhàn)斗系統(tǒng)的實(shí)現(xiàn)
5.3.1客戶端戰(zhàn)斗系統(tǒng)功能模塊
圖5-4客戶端戰(zhàn)斗系統(tǒng)功能模塊
說明:
戰(zhàn)斗系統(tǒng)主要包含戰(zhàn)斗角色、戰(zhàn)斗動畫和戰(zhàn)斗指令菜單三個模塊;
戰(zhàn)斗指令菜單類型分為人物和寵物兩種,分別用于下達(dá)人物和寵物戰(zhàn)斗指令,并發(fā)送戰(zhàn)斗指令消息給服務(wù)器;
戰(zhàn)斗角色由角色圖形、動畫控制器和血條組成,通過動畫控制器切換不同動作的動畫,主要負(fù)責(zé)戰(zhàn)斗角色的圖形顯示;
戰(zhàn)斗動畫模塊主要有動畫計數(shù)、把接收到的所有動畫消息轉(zhuǎn)換為戰(zhàn)斗動畫類以及播放戰(zhàn)斗動畫三個功能;
動畫計數(shù)主要是為了等待戰(zhàn)斗中所有正在播放的角色動作動畫、特效動畫播放完,角色動作動畫或特效動畫開始時會+1動畫計數(shù),結(jié)束時會-1動畫計數(shù),動畫計數(shù)為0后,當(dāng)前單位行動結(jié)束,下一個行動單位開始行動;
播放戰(zhàn)斗動畫模塊根據(jù)戰(zhàn)斗動畫類數(shù)據(jù)播放不同行為的動畫(主要使用協(xié)程來控制戰(zhàn)斗角色的移動、切換戰(zhàn)斗角色的動作動畫、添加特效等)。
5.3.2客戶端戰(zhàn)斗系統(tǒng)相關(guān)數(shù)據(jù)類型
//戰(zhàn)斗動畫類
publicclassBATTLE_ANIM
{
publicushortnActorIndex;//行動方索引
publicushort[]nTargetIndex=newushort[10];//目標(biāo)索引
publicushortaction_type;//行動類型
publicushortnParam;//參數(shù)(根據(jù)行動類型而定,如使用技能則是技能ID,使用物品則是物品欄位置)
publicushortnAnimType;//技能動畫類型
publicushortnEffectID;//技能特效ID
publicushortnTargetCount;//目標(biāo)總數(shù)(nTargetIndex數(shù)組中值不為0的個數(shù))
publicushortnReactionIndex;//當(dāng)前受影響的目標(biāo)索引
publicshortnActorMp;//行動方Mp影響(多用于計算技能使用者的Mp消耗)
publicshort[]nTargetHp=newshort[10];//目標(biāo)索引對應(yīng)的目標(biāo)Hp影響
}
5.3.3進(jìn)入戰(zhàn)斗后初始化戰(zhàn)斗角色
收到來自服務(wù)器的戰(zhàn)斗初始化消息后,切換到戰(zhàn)斗場景,并根據(jù)戰(zhàn)斗初始化消息中的battleSprites數(shù)組(包含戰(zhàn)斗角色的玩家ID、圖形及動畫控制器ID、名字、Hp和Mp等數(shù)據(jù))動態(tài)生成對應(yīng)的戰(zhàn)斗角色。
并且從戰(zhàn)斗初始化消息中的battleSprites數(shù)組中,對比玩家ID(客戶端在登錄游戲后,理應(yīng)早已得到玩家ID,那么在這里與battleSprites數(shù)組的玩家ID進(jìn)行對比)查找自身角色和寵物的索引,用變量保存該索引,用于下達(dá)戰(zhàn)斗指令。
5.3.4下達(dá)戰(zhàn)斗指令并發(fā)送戰(zhàn)斗指令消息
下達(dá)戰(zhàn)斗指令實(shí)質(zhì)是地對戰(zhàn)斗指令消息的賦值。
一般是先下達(dá)人物戰(zhàn)斗指令,如有參戰(zhàn)寵物,再下達(dá)戰(zhàn)斗指令。在本文4.3.2中,進(jìn)入戰(zhàn)斗時,客戶端已能獲得自身人物和寵物在戰(zhàn)斗中的索引,若是輪到人物下達(dá)戰(zhàn)斗指令,則戰(zhàn)斗指令消息的nActorIndex是人物的索引,若是輪到寵物下達(dá)戰(zhàn)斗指令,則指令消息的nActorIndex是寵物的索引,分情況賦值即可,然后根據(jù)不同的行動類型對指令消息的nActionType行動類型賦值,最后通過點(diǎn)選目標(biāo)對指令消息的nTargetIndex進(jìn)行賦值。
當(dāng)下達(dá)完人物和寵物的戰(zhàn)斗指令后,分別發(fā)送對應(yīng)的戰(zhàn)斗指令消息。
戰(zhàn)斗指令菜單的UI實(shí)現(xiàn)千變?nèi)f化,本文不作闡述,使用最簡單的按鈕即可實(shí)現(xiàn)。
下圖為實(shí)踐項目的指令菜單,其中玩家選擇了使用技能的行動,并即將點(diǎn)選技能:
圖5-5指令菜單
5.3.5接收戰(zhàn)斗動畫消息
根據(jù)每一條接收到的戰(zhàn)斗動畫消息對new出來的戰(zhàn)斗動畫類賦值,并push_back到一個順序容器(可考慮List)。
5.3.6收到戰(zhàn)斗動畫播放消息并播放戰(zhàn)斗動畫
當(dāng)接收到來自服務(wù)器的戰(zhàn)斗動畫播放消息后,客戶端開始從頭到尾遍歷存放了多個戰(zhàn)斗動畫類的順序容器,根據(jù)戰(zhàn)斗動畫類的數(shù)據(jù),逐個播放動畫。
戰(zhàn)斗動畫的實(shí)現(xiàn)方式主要是依靠協(xié)同程序和動畫計數(shù)器。角色播放動作動畫(除待機(jī))或每往場景中添加一個特效動畫,動畫計數(shù)加1,角色播放動作動畫(除待機(jī))結(jié)束時調(diào)用方法切回待機(jī)動畫并且動畫計數(shù)-1,特效動畫播放結(jié)束時銷毀自身并且調(diào)用方法把動畫計數(shù)減1,當(dāng)動畫所有協(xié)程結(jié)束返回并且動畫計數(shù)為0時,當(dāng)前動畫播放完畢,開始播放下一個動畫。
當(dāng)播放完所有戰(zhàn)斗動畫類后,清空容器,若一方全體陣亡,則戰(zhàn)斗結(jié)束退出戰(zhàn)斗場景,否則進(jìn)入下一回合,玩家開始下達(dá)新回合的戰(zhàn)斗指令。
根據(jù)戰(zhàn)斗動畫類的行動類型和特效播放方式的不同,動畫播放實(shí)現(xiàn)方式也不同,由于動畫的實(shí)現(xiàn)較為復(fù)雜,本文在5.3.7小節(jié)單獨(dú)以普通攻擊動畫進(jìn)行較詳細(xì)的闡述,讀者可結(jié)合本小節(jié)和5.3.7小節(jié)進(jìn)行理解。
下面是各種戰(zhàn)斗動畫的實(shí)現(xiàn)方式:
普通攻擊動畫協(xié)程
①行動者角色執(zhí)行協(xié)程Move(),從自身位置移動到目標(biāo)角色位置,到達(dá)后協(xié)程結(jié)束返回;
②行動者播放攻擊動作動畫,目標(biāo)播放受傷動作動畫并顯示目標(biāo)扣血數(shù)值,更新角色Hp/Mp,若角色Hp為0則播放死亡動作動畫;
③使用循環(huán)和yieldreturn0語句直到動畫計數(shù)為0(即攻擊動畫、受傷動畫播放完)跳出循環(huán);
④行動者角色執(zhí)行協(xié)程Back(),回到原本的位置,到達(dá)原本的位置后協(xié)程結(jié)束返回;
⑤協(xié)程結(jié)束返回。
攻擊技能動畫協(xié)程
①行動者角色執(zhí)行協(xié)程Move(),從自身位置移動到目標(biāo)角色位置,到達(dá)后協(xié)程結(jié)束返回;
②行動者播放攻擊動作動畫,添加并播放技能特效動畫,目標(biāo)播放受傷動作動畫并顯示目標(biāo)扣血數(shù)值,更新角色Hp/Mp,若角色Hp為0則播放死亡動作動畫;
③使用while循環(huán)和yieldreturn0語句直到動畫計數(shù)為0(即攻擊動畫、受傷動畫、特效動畫播放完),后跳出循環(huán);
④行動者角色執(zhí)行協(xié)程Back(),回到原本的位置,到達(dá)原本的位置后Back()協(xié)程結(jié)束返回;
⑤協(xié)程結(jié)束返回。
魔法技能(同步型特效)動畫協(xié)程
①行動者播放施法動作動畫,遍歷所有目標(biāo),并在目標(biāo)位置上添加并播放特效動畫,目標(biāo)播放受傷動作動畫并顯示扣血數(shù)值,更新角色Hp/Mp,若角色Hp為0則播放死亡動作動畫;
②使用while循環(huán)和yieldreturn0語句直到動畫計數(shù)為0(即攻擊動畫、受傷動畫、特效動畫播放完),后跳出循環(huán);
③協(xié)程結(jié)束返回。
動畫效果如下圖:
圖5-6魔法技能(同步型特效)動畫效果
魔法技能(異步型特效)動畫協(xié)程
①行動者播放施法動作動畫,遍歷所有目標(biāo),并在目標(biāo)位置上添加并播放特效動畫,目標(biāo)播放受傷動作動畫并顯示扣血數(shù)值,更新角色Hp/Mp,若角色Hp為0則播放死亡動作動畫,遍歷中使用yieldreturn幀數(shù)/秒數(shù)實(shí)現(xiàn)延遲,從而達(dá)到每個目標(biāo)身上出現(xiàn)的特效動畫時間不一樣;
②使用while循環(huán)和yieldreturn0語句直到動畫計數(shù)為0(即攻擊動畫、受傷動畫、特效動畫播放完),后跳出循環(huán);
③協(xié)程結(jié)束返回。
動畫效果如下圖:
圖5-7魔法技能(異步型特效)動畫效果
魔法技能(彈射型特效)動畫協(xié)程
①行動者播放施法動作動畫,行動者身上添加一個循環(huán)播放的特效動畫;
②遍歷目標(biāo),使用協(xié)程控制特效動畫的移動,使特效移動到目標(biāo)的位置,到達(dá)位置后,目標(biāo)播放受傷動作動畫并顯示扣血數(shù)值,更新角色Hp/Mp,若角色Hp為0則播放死亡動作動畫,再讓特效移動到下一個目標(biāo)的位置,如此類推,直到最后一個目標(biāo),手動摧毀特效;
③協(xié)程結(jié)束返回。
動畫效果如下圖:
圖5-8魔法技能(彈射型特效)動畫效果
魔法技能(發(fā)射型特效)動畫協(xié)程
①行動者播放施法動作動畫,遍歷目標(biāo),行動者身上添加數(shù)量與目標(biāo)數(shù)相同循環(huán)播放的特效動畫,并增加同等的動畫計數(shù);
②每個特效自身執(zhí)行協(xié)程讓自身移向?qū)?yīng)目標(biāo)的位置,到達(dá)后動畫計數(shù)減1,特效銷毀自身,目標(biāo)播放受傷動作動畫并顯示扣血數(shù)值,更新角色Hp/Mp,若角色Hp為0則播放死亡動作動畫;
③使用while循環(huán)和yieldreturn0語句直到動畫計數(shù)為0(即攻擊動畫、受傷動畫、特效動畫播放完),后跳出循環(huán);
④協(xié)程結(jié)束返回。
動畫效果如下圖:
圖5-9魔法技能(發(fā)射型特效)動畫效果
使用物品動畫協(xié)程
①行動者播放施法動作動畫,并在所有目標(biāo)身上添加并播放用于恢復(fù)的特效動畫并顯示數(shù)值,更新角色Hp/Mp;
②使用while循環(huán)和yieldreturn0語句直到動畫計數(shù)為0(即攻擊動畫、受傷動畫、特效動畫播放完),后跳出循環(huán);
③協(xié)程結(jié)束返回。
5.3.7戰(zhàn)斗動畫實(shí)現(xiàn)細(xì)述
本小節(jié)以魔法技能動畫(彈射型特效)的實(shí)現(xiàn)為例進(jìn)行細(xì)述,以便讀者理解實(shí)現(xiàn)原理。
相關(guān)偽代碼如下:
//動畫播放協(xié)程
IEnumeratorPlayAnim()
{
while(l_AnimList不為空)//存放戰(zhàn)斗動畫類的list容器不為空
{
//從容器中獲得頭一個戰(zhàn)斗動畫類
BATTLE_ANIMbattleAnim=l_AnimList[0];
switch(battleAnim.action_type)//判斷行動類型
{
case普通攻擊:
yieldreturnStartCoroutine(Attack(battleAnim));
break;
case使用技能:
根據(jù)battleAnim.nParam查詢數(shù)據(jù)庫技能表獲得技能動畫類型
battleAnim.nAnimType=技能動畫類型
switch(battleAnim.nAnimType)//判斷技能動畫類型
{
case攻擊技能動畫:
yieldreturnStartCoroutine(MagicAttack(battleAnim));
break;
case魔法技能動畫(彈射型特效):
yieldreturnStartCoroutine(MagicBounce(battleAnim));
break;
……
}
break;
case使用物品:
yieldreturnStartCoroutine(Item(battleAnim));
break;
}
while(動畫計數(shù)器!=0)//(一幀一次循環(huán))
{
//下一幀再回到這里執(zhí)行下一次循環(huán)
yieldreturn1;
}
l_AnimList.Remove(0);//清除本次播放完的戰(zhàn)斗動畫類
}
//所有動畫播放完
if(一方全體死亡)
戰(zhàn)斗結(jié)束
else
進(jìn)入下一回合,玩家下達(dá)指令
}
說明:
PlayAnim協(xié)同程序主要是遍歷存放戰(zhàn)斗動畫類的list容器,通過遍歷逐個播放戰(zhàn)斗動畫類數(shù)據(jù)所包含的動畫,通過類型的判斷,執(zhí)行不同的協(xié)同程序?qū)崿F(xiàn)不同類型動畫的播放。
//魔法技能動畫(彈射型特效)協(xié)程
IEnumeratorMagicBounce(BATTLE_ANIMbattleAnim)
{
行動者(施法者)播放施法動作動畫;
根據(jù)特效ID動態(tài)加載特效預(yù)設(shè);
由特效預(yù)設(shè)動態(tài)生成特效effect;
把effect移到到施法者的位置上;
動畫計數(shù)+1;
for(inti=0;i<battleAnim.nTargetCount;i++)//遍歷目標(biāo)
{
獲得battleAnim.nTargetIndex[i]目標(biāo)索引并根據(jù)索引獲取目標(biāo)角色
destPos=目標(biāo)角色的位置
while(effect的位置!=destPos)
{
特效的位置=Vector3.MoveTowards(特效的位置,destPos,400*Time.deltaTime);//即根據(jù)速度移向目標(biāo)位置
yieldreturn0;
}
目標(biāo)播放受傷動作動畫并顯示扣血
}
遍歷完所有目標(biāo)后,銷毀特效
動畫計數(shù)-1
}
說明:
MagicBounce協(xié)同程序主要是控制特效的移動,實(shí)現(xiàn)彈射型特效動畫的播放。
最終的動畫效果為:行動者施法,技能特效從行動者身上移向第一個目標(biāo),特效到達(dá)第一個目標(biāo)的位置后目標(biāo)受傷并扣血,特效繼續(xù)移向下一個目標(biāo),如此類推,直到最后一個目標(biāo)后,技能動畫結(jié)束,銷毀特效,協(xié)程結(jié)束返回到PlayAnim(),PlayAnim()繼續(xù)遍歷播放下一個動畫。
其他動畫類型與上述例子類似,只要讀者理解好協(xié)同程序的執(zhí)行原理和動畫計數(shù)器的作用,相信其他動畫類型的實(shí)現(xiàn)也能掌握個大概,甚至能實(shí)現(xiàn)出更多的技能動畫類型。
第6章項目測試
6.1進(jìn)入戰(zhàn)斗測試
圖6-1進(jìn)入戰(zhàn)斗
從測試截圖可以看到,游戲進(jìn)入了戰(zhàn)斗畫面,并且成功初始化了所有角色。
6.2普通攻擊功能測試
圖6-2攻擊測試截圖1
圖6-3攻擊測試截圖2
圖6-4攻擊測試截圖3
從圖6-2可以看出,行動角色正移向目標(biāo),圖6-3為攻擊目標(biāo),圖6-4為攻擊完退回原來的位置,成功實(shí)現(xiàn)了普通攻擊動畫。
6.3使用技能功能測試
圖6-5使用技能測試截圖1
從上圖中我們發(fā)現(xiàn)了一個問題,在技能特效沒有播放完成時,下一個行動單位就已經(jīng)開始行動了,因?yàn)槲覀兂绦蜻€沒有判斷特效什么時候結(jié)束,而且不同的特效動畫時長不一樣。
解決方案:加入動畫計數(shù),在每一個單獨(dú)的特效生成時,使動畫計數(shù)+1,在特效自身播放結(jié)束的最后一幀,調(diào)用方法使動畫計數(shù)-1,并且銷毀自身,當(dāng)動畫計數(shù)等于0時,表明這個單位行動涉及到的動畫都已經(jīng)播放完,則可以開始下一個單位的行動。
圖6-6使用技能測試截圖2
加入動畫計數(shù)之后,從上圖可以看出角色正在施法,并且特效正在播放,其他單位沒有進(jìn)行行動,直到特效動畫播放完成,下一個單位才開始行動,解決了問題。
6.4使用物品功能測試
圖6-7使用物品測試截圖1
圖6-8使用物品測試截圖2
從圖6-7看出角色使用物品的特效正在播放,并且我方角色Hp數(shù)值較低。在圖6-8中,顯示了恢復(fù)數(shù)值,并且我方全體角色Hp得到了恢復(fù),實(shí)現(xiàn)了使用物品動畫。
結(jié)論
經(jīng)過對Unity以及回合制網(wǎng)游的長時間深入的研究分析,并且伴隨著畢業(yè)設(shè)計以及論文的工作,最終成功達(dá)到目的實(shí)現(xiàn)了包含主要功能的回合制網(wǎng)游戰(zhàn)斗系統(tǒng)。
在客戶端戰(zhàn)斗動畫播放的實(shí)現(xiàn)里,采用Unity協(xié)同程序的方案實(shí)現(xiàn)也使本戰(zhàn)斗系統(tǒng)得到創(chuàng)新和突破,能夠?qū)崿F(xiàn)多種不同的特效播放方式,并且相信還能實(shí)現(xiàn)更多華麗特別的特效播放方式,有待繼續(xù)研究。
經(jīng)過多次的測試驗(yàn)證,沒有出現(xiàn)嚴(yán)重的漏洞或問題,證明本論文的研究和實(shí)現(xiàn)方式是可行的。
來之不易的成功讓筆者十分激動,也為筆者對回合制網(wǎng)游戰(zhàn)斗系統(tǒng)的后續(xù)開發(fā)增加了極大的信心。
由于時間和個人能力有限,本論文的研究、分析和實(shí)現(xiàn)難免存在錯誤和不足之處,還懇請各位讀者提出意見,讓筆者為其改善或更正。
由于回合制戰(zhàn)斗系統(tǒng)邏輯復(fù)雜,加上本人闡述能力有限,讀者可能需要反復(fù)進(jìn)行閱讀和理解,如有疑問和意見懇請讀者聯(lián)系本人。
希望本文能夠?yàn)樽x者提供幫助或啟發(fā),也希望有更多志同道合熱衷于回合制戰(zhàn)斗系統(tǒng)開發(fā)的朋友加入研究、開發(fā)以及進(jìn)行學(xué)術(shù)交流,為回合制戰(zhàn)斗系統(tǒng)尋求更多創(chuàng)新和突破。
參考文獻(xiàn)
[1]鄭莉,董淵,何江舟編著.C++語言程序設(shè)計(第四版)[M].北京:清華大學(xué)出版社,2010.398-478.
[2]劉琰,王清賢,劉龍,陳熹編著.Windows網(wǎng)絡(luò)編程[M].北京:機(jī)械工業(yè)出版社,2014.56-221.
[3]A神.網(wǎng)絡(luò)連接:unityNetWork與socket的對比(一)[Z].
/thread-6966-1-1.html
,2014-11-14
[4]黃祖翔.unity2d-第三課:sprite動畫編輯及動畫事件[Z]./thread-420420-1-1.html,2014-11-12
[5]ChevyRay.snaker7譯.Unity3D協(xié)程介紹以及使用[Z].[Online]Available:
/huang9012/article/details/38492937
(2014-08-11)
[6]FengYu.UGUI教程-12.事件接口[Z].[Online]Available:/thread-1487-1-1.html(2015-1-25)
[7]thirdpig.關(guān)于對stl容器的遍歷和刪除[Z].[Online]Available:
/s/blog_6a5b0bad0100nz59.html
(2011-01-12)
[8]秦元培.
Unity3D游戲開發(fā)之SQLite讓數(shù)據(jù)庫開發(fā)更簡單
[Z].[Online]Available:
/qinyuanpei/article/details/46812655
(2015-07-09)
[9]宣雨松.Unity3D研究院之在Unity中打開第三方數(shù)據(jù)庫配合Android開發(fā)(三十二)[Z].[Online]Available:
/archives/1454
(2012-08-09)
[10]
tiaotiaoyly
.
使用MySQLconnector/C++鏈接MySQL數(shù)據(jù)庫
[Z].[Online]Available:/tiaotiaoyly/article/details/5174772(2010-01-11)
致謝
本論文是在廣州大學(xué)華軟軟件學(xué)院游戲系孟輝老師指導(dǎo)下完成的。
本論文能夠順利完成,首先要感謝我的論文指導(dǎo)老師孟輝老師,感謝孟輝老師愿意當(dāng)我的論文指導(dǎo)老師,從論文選題命題、開題、撰寫與修改直到戰(zhàn)斗系統(tǒng)的實(shí)現(xiàn)和測試,孟輝老師給予了我全程悉心的指導(dǎo)和幫助。同時,本論文內(nèi)容以及項目《PKer》所涉及的知識極大部分都來自孟輝老師所教授的《網(wǎng)絡(luò)游戲基礎(chǔ)》課程,感謝孟輝老師在課程中的細(xì)心講解,以及對我提出的眾多刨根問底疑問的回答,讓我在socket網(wǎng)絡(luò)編程相關(guān)方面打下了扎實(shí)的基礎(chǔ)。
感謝四年以來廣州大學(xué)華軟軟件學(xué)院所有給我講授過課程的老師,特別是我系游戲系的老師,是你們的悉心教導(dǎo)讓我日積月累、逐步深入地掌握游戲編程的相關(guān)知識。
感謝我的母校廣州大學(xué)華軟軟件學(xué)院以及我所在的系游戲系,感謝華軟學(xué)院開設(shè)游戲系,在全國高校中開辟先河,感謝華軟學(xué)院讓我轉(zhuǎn)入游戲系,感謝游戲系的對我的悉心培育。感謝華軟感謝游戲系,是你們讓我邁入游戲行業(yè),是你們讓我這個高考落敗的文科生找到了人生的新方向。
感謝IOCP服務(wù)器框架“HP-Socket”的作者小怪獸,高效穩(wěn)定的服務(wù)器給與我更大的信息,框架使我的研究減少了很多憂患,也是我項目能夠成功的必不可少的前提。
另外,感謝參考文獻(xiàn)里分享博客或文章的各位前輩,你們的實(shí)踐和無私分享讓我獲益匪淺。
最后,還要感謝我的項目《PKer》的GameFriends團(tuán)隊所有成員,是你們的無私付出為我的項目《PKer》提供美術(shù)支持,使《PKer》得到不斷完善和升華。在接下來為數(shù)不多的在校日子里,我和我的團(tuán)隊,會繼續(xù)開發(fā)和完善《PKer》項目以及其回合制戰(zhàn)斗系統(tǒng)。
由于
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年中國FM自動選臺收音機(jī)望遠(yuǎn)鏡數(shù)據(jù)監(jiān)測研究報告
- 2025年中國BOPP鍍鋁膜數(shù)據(jù)監(jiān)測研究報告
- 2025年中國2、5-二甲基苯胺數(shù)據(jù)監(jiān)測報告
- 2025至2030年中國集中操作式電梯井筒模市場分析及競爭策略研究報告
- 2025至2030年中國鋁合金吸頂燈市場分析及競爭策略研究報告
- 2025至2030年中國茴香粉市場分析及競爭策略研究報告
- 2025至2030年中國砼攪拌站市場分析及競爭策略研究報告
- 2025至2030年中國電力控制開關(guān)柜市場分析及競爭策略研究報告
- 2025至2030年中國深溝外球面球軸承市場分析及競爭策略研究報告
- 2025至2030年中國汽車儲液器支架市場分析及競爭策略研究報告
- 初三勵志主題班會:初三第一次班會幻燈片PPT
- GB/T 42910-2023無機(jī)膠粘劑高溫壓縮剪切強(qiáng)度試驗(yàn)方法
- 2022年江蘇省射陽中等專業(yè)學(xué)校招聘考試真題及答案
- 給攪拌站送石子合同范本
- 2023年副主任醫(yī)師(副高)-學(xué)校衛(wèi)生與兒少衛(wèi)生(副高)考試歷年真題集錦帶答案
- 法律基礎(chǔ)(第4版)PPT完整全套教學(xué)課件
- 倉管應(yīng)聘求職簡歷表格
- 五年級下冊語文期末考試學(xué)霸奪冠解密卷人教部編版含答案
- 房屋加固工程監(jiān)理規(guī)劃
- 一級煙草專賣管理師理論考試題庫(含答案)
- von frey絲K值表完整版
評論
0/150
提交評論