溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結

發(fā)布時間:2020-06-18 05:17:20 來源:網絡 閱讀:15739 作者:shahdza 欄目:游戲開發(fā)

【嘮叨】

    今天結束了本學期任務最為艱巨的項目實訓課程,由于項目組里其他成員基本都已經找到實習了,然后他們都去實習了。只留下我和一個小伙伴在一起搞項目實訓的小游戲。經過一個月與小伙伴的配合開發(fā),做了一個勉強可以玩的一個小游戲demo,因為平時其他課程也比較繁重,所以游戲做得非常爛~(>_<)~。

    我們本來打算做一款類似COC、海盜奇兵、口袋侏羅紀、城堡爭霸的城戰(zhàn)類的單機Demo。結果……哎說多了都是淚啊,經驗不足,吸取教訓了。


【經驗教訓】

    由于時間比較緊張,加上自身也沒有大項目開發(fā)的經驗,所以一開始沒有太重視去考慮游戲整體架構的問題,都是寫一點算一點,從而在開發(fā)到一半,發(fā)現很多代碼沒有做到復用,而是一直復制張貼的。然后后期也沒有時間去重構,結果導致代碼寫得比較凌亂不堪。

【收獲】

    雖然做的效果沒有達到預期,但是還是從項目實訓中有非常多的收獲的。

    1、再一次學習了一遍C++,對C++有了更深入的了解。

    2、提前學習了各種文件讀取解析的方式:JSON、XML、CSV、Sqlite。(最后我們采用了CSV來存儲靜態(tài)數據,用Sqlite來存儲玩家數據)。

    3、掌握了游戲開發(fā)的一些基本流程。

    4、學習和掌握了cocos2d-x游戲引擎,cocos studio界面編輯器。

    5、掌握了觀察者模式委托模式的運用。

    6、學習了游戲的自動尋路的A*算法。


【項目Demo】

    代碼寫的比較爛,但是我依然又放到了guthub上,只是為了想要存儲我寫的每一份代碼。

    因為放在本地硬盤,需要占存儲空間的。~~~~(>_<)~~~~ 。

    代碼托管:https://github.com/shahdza/Cocos_Ring


【成果演示】

    做得挺爛的,大家看了不要噴。。。

    素材均來自《城堡爭霸》,本游戲只做學習研究,切勿商用,以免侵權。。。

    游戲概述:

        1、玩家城池:可以移動設施、升級設施、新建設施、管理士兵、管理英雄。

        2、關卡戰(zhàn)斗:可以派出士兵自動尋路***,可以控制英雄移動,***指定建筑,釋放技能。

        3、戰(zhàn)略地圖通過迷霧遮罩,升級雷達,可以擴大地圖的可視范圍。

    視頻鏈接:http://v.youku.com/v_show/id_XOTM0NzQ3NDQ4.html


【開發(fā)環(huán)境】

    Cocos2d-x 3.4

    Cocos Studio 1.6.0 (UI編輯器、動畫編輯器)




【一些重要的收獲】


1、分辨率適配問題

    由于地圖比較大,可以通過拖動來顯示地圖的其他區(qū)域部分,所以分辨率的適配比較簡單。只要寬度或高度適配即可。


2、地圖的移動與縮放

    可以參見這篇文章:http://cn.cocos2d-x.org/tutorial/show?id=1479

    根據手指觸摸的數量,來判斷是移動還是縮放。

    > 一根手指:移動地圖,實現比較簡單。

    > 兩根或多根手指:看做兩根手指,縮放地圖。需要通過一定的公式來計算,縮放前和縮放后的坐標轉換。(具體參見上述文章)。

    對于手指滑動后,地圖又具有慣性地減速移動:可以根據手指滑動的速度快慢,計算出一個加速度(其實可以通過觸摸事件onTouchMoved中Touch的getDelta()函數獲得),然后通過在update函數中進行減速計算。

    縮放的前后坐標計算,如下圖所示:

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結


3、玩家城池中,建筑的坐標定位

    對于45°坐標,可以參照這篇文章:http://blog.sina.com.cn/s/blog_6807f539010103ce.html

    由于城池中采用的是斜45°的2.5D視角,所以需要進行坐標的轉換操作。

    先將城池地圖進行瓦片分割,分成一塊一塊區(qū)域。如下所示,其實可以看到地圖是一個個小方塊組成的。

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結


4、關于建筑的觸摸移動

    當建筑需要移動它的位置的時候,需要屏蔽地圖層的移動和縮放,不然你回發(fā)現你的建筑和地圖都在移動?。。?br />

    做法是:觸摸到建筑,進行移動時,其實cocos已經有了觸摸吞噬的函數

listener->setSwallowTouches(true);即可。

    當然還有一種比較好的做法是:定義一個專門處理觸摸事件的觸摸層,來管理場景中所有元素的觸摸事件,并按照觸摸的優(yōu)先級進行排序,然后再按照優(yōu)先級進行分發(fā)觸摸響應事件(因為一般觸摸只會有一個事件作出響應,也就是說每次的觸摸只會有一個元素執(zhí)行了觸摸事件)。


5、關于設施升級、時間點觸發(fā)某事件等一系列的響應事件

    在設施進行升級、或者當到大某一時間點時,可能需要觸發(fā)一些任務響應事件。可以通過委托模式來處理,即在做某一事件時,給該事件委托一個函數(可以通過函數指針來實現)。然后當某一事件完成后,調用該委托函數(可以不指定為某一特定的函數,而是通過函數指針的形式來調用)。

    另一種做法是:通過觀察者模式,即一個事件對某一消息進行訂閱,然后另一個事件在執(zhí)行完后,發(fā)布該消息,然后第一個事件就接受到了消息,執(zhí)行相應的處理函數。

    例如:士兵***建筑時,士兵執(zhí)行完***動作,然后建筑需要作出“扣血”這一事件。就可以通過委托函數來完成,即實現不知道需要執(zhí)行哪個建筑的“扣血”事件。而是通過函數指針來調用對應士兵所***的那個建筑的“扣血”事件處理函數。

    至于觀察者模式可參見:http://shahdza.blog.51cto.com/2410787/1611575


6、對于游戲中時間控制的問題

    因為是一個城戰(zhàn)類的游戲,所以設施的升級是需要一定的時間的,比如升級需要10分鐘。還有采礦場每分鐘可以生產10個金幣等等,都是需要用到“時間”。

    做法是:拿設施的升級操作舉例,在點擊對設施進行升級時,可以記錄一個升級時的“時間戳”,并存儲到數據庫的該設施的一個字段中,然后再游戲進行的過程中,只要不斷獲取當前時間的“時間戳”,然后減去之前記錄的點擊升級時的“時間戳”。差值即為從升級到目前過去了多少時間,然后就可以做一些列的操作了。

    關于如何獲取時間戳,參見:

// 獲取時間戳
int GlobalManager::getTimeStamp()
{
    timeval tm;
    gettimeofday(&tm, NULL);
    return tm.tv_sec; // 返回當前時間對應的時間戳,單位:秒
}


7、戰(zhàn)斗界面的AI(自動尋路、自動***)

    也可以參見:http://cn.cocos2d-x.org/tutorial/show?id=1638

    我的做法比較簡單,使用狀態(tài)機:移動、***、閑置、已陣亡然后每隔0.5秒執(zhí)行一次狀態(tài)轉換的操作。

    首先將地圖分成一塊一塊,然后用二維bool矩陣來標記障礙物,然后控制士兵、英雄的移動。

    > 對于士兵:設置定時器,每隔0.5秒執(zhí)行一次動作。若士兵還未鎖定***目標,則遍歷設施,找到最近的設施作為目標。若士兵鎖定了***目標,則可以通過A*算法檢測上下左右、左上、右上、左下、右下八個方向的瓦片格子中,是空地,并且里目標建筑最近的,就將士兵往那個格子移動(至于距離:可以通過h函數來估計,我采用的是估計函數:曼哈頓距離,即x坐標之差的絕對值 + y坐標之差的絕對值),這樣士兵可以自動繞過障礙物。若目標設施在士兵的可***范圍內,則對設施進行***。

    我為什么要嘗試每隔一定時間,檢測士兵的八個方向,離目標最近,然后移動過去呢?是因為如果士兵鎖定了目標后,然后執(zhí)行完整的A*算法,計算出完整的移動路徑,這樣的操作是非常耗時的。對于很多個士兵同時執(zhí)行完整的A*算法進行尋路,可能就會出現卡頓的現象。而我的做法正好避免了這樣的問題,將A*算法的每一步操作都均攤到每個0.5秒的時間。

    > 對于英雄:通過觸摸來控制移動,和***某一目標。觸摸地圖某一位置,英雄移動的操作與士兵的自動尋路和自動***思路類似。

    > 對于可***型建筑:設施定時器,每個0.5秒執(zhí)行一次。遍歷我方士兵、英雄。若有士兵在建筑的可***范圍內,則***我方。


8、頭文件的管理

    由于類和類之間不是獨立存在的,必然會有頭文件的相互引用問題,所以我就額外將所有的類的頭文件都放到一個public.h文件中,那么其他類只要引用"public.h"頭文件即可,而不需要考慮需要引用哪些哪些頭文件。

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結        Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結

    然后在 public.h文件開頭加上文件預編譯指令:這樣就可以保證頭文件不會被多次編譯。

#ifndef __Public_H__
#define __Public_H__

#endif


9、全局變量的管理

    也是當獨放到一個頭文件中進行管理的:包含了圖片資源的路徑、一些全局變量、數據文件的路徑等。

    

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結


10、CocosStudio的使用

    本游戲用的時Cocos Studio 1.6.0版本。其實這個版本是已經非常強大了,不僅可以做界面UI,而已可以制作角色動畫。

    使用方法:到官網學習。


11、數據的管理

    寫了一個專門管理游戲數據的單例類DataManager。用于數據的加載、獲取、更新等操作。

    對于表現層和控制層有哪些數據修改的請求操作,都通過DataManager進行管理,然后再重新繪制游戲的UI。

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結


12、一些全局的輔助函數的管理

    也是用了一個GlobalManager單例類來進行管理。提供游戲中的相關的輔助函數。

    如:獲取最大最小值、地圖坐標與瓦片坐標的轉換、判斷一個點是否落在多邊形內、獲取時間戳、×××數據和字符串數據的轉換、場景的切換管理等功能。

Cocos實戰(zhàn)篇[3.4]——仿COC的一個小Demo總結




【遇到的問題】


1、瓦片坐標與地圖坐標的轉換

    計算相應的轉換公式。


2、兩頭文件相互引用

    需要在類之前,對另一個類做類的聲明。


3、野指針問題

    當兩個建筑都鎖定同一個士兵后,第一個建筑執(zhí)行完***動畫,然后讓該士兵作出扣血事件,正好士兵血沒了,就要從圖層中移除。可是呢?第二個建筑也鎖定了該目標啊,執(zhí)行玩***動畫后,調用該士兵的扣血事件,出現了異常。因為該士兵已被釋放。。。

    解決方案:

    (1)一直保留士兵,陣亡后,不從圖層中移除,而是將士兵隱藏。

    (2)延遲士兵的移除操作。由于建筑是每個0.5秒尋找一次目標,然后對其進行***。那么我們只要在士兵陣亡后,用一個變量isDeath來標記士兵是否陣亡,然后建筑在遍歷士兵時,跳過isDeath=true的士兵,那么建筑在下一個0.5秒就不會再指向該士兵。那么士兵只要在陣亡后,標記isDeath=true,然后延遲1秒鐘后,調用remove()函數從圖層中移除,就不會出現野指針異常的問題。

    (3)同樣也可以通過觀察者模式,建筑對士兵的陣亡消息進行訂閱,然后當士兵陣亡后,發(fā)布陣亡消息。建筑在接收到陣亡消息后,將鎖定的目標target指針置為空NULL,即可。


4、中文亂碼問題

    使用UTF-8即可。


5、游戲AI問題

    學習了A*算法。


6、還有其他一些小問題,已忘………………



向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI