您好,登錄后才能下訂單哦!
【嘮叨】
今天結束了本學期任務最為艱巨的項目實訓課程,由于項目組里其他成員基本都已經找到實習了,然后他們都去實習了。只留下我和一個小伙伴在一起搞項目實訓的小游戲。經過一個月與小伙伴的配合開發,做了一個勉強可以玩的一個小游戲demo,因為平時其他課程也比較繁重,所以游戲做得非常爛~(>_<)~。
我們本來打算做一款類似COC、海盜奇兵、口袋侏羅紀、城堡爭霸的城戰類的單機Demo。結果……哎說多了都是淚啊,經驗不足,吸取教訓了。
【經驗教訓】
由于時間比較緊張,加上自身也沒有大項目開發的經驗,所以一開始沒有太重視去考慮游戲整體架構的問題,都是寫一點算一點,從而在開發到一半,發現很多代碼沒有做到復用,而是一直復制張貼的。然后后期也沒有時間去重構,結果導致代碼寫得比較凌亂不堪。
【收獲】
雖然做的效果沒有達到預期,但是還是從項目實訓中有非常多的收獲的。
1、再一次學習了一遍C++,對C++有了更深入的了解。
2、提前學習了各種文件讀取解析的方式:JSON、XML、CSV、Sqlite。(最后我們采用了CSV來存儲靜態數據,用Sqlite來存儲玩家數據)。
3、掌握了游戲開發的一些基本流程。
4、學習和掌握了cocos2d-x游戲引擎,cocos studio界面編輯器。
5、掌握了觀察者模式、委托模式的運用。
6、學習了游戲的自動尋路的A*算法。
【項目Demo】
代碼寫的比較爛,但是我依然又放到了guthub上,只是為了想要存儲我寫的每一份代碼。
因為放在本地硬盤,需要占存儲空間的。~~~~(>_<)~~~~ 。
代碼托管:https://github.com/shahdza/Cocos_Ring
【成果演示】
做得挺爛的,大家看了不要噴。。。
素材均來自《城堡爭霸》,本游戲只做學習研究,切勿商用,以免侵權。。。
游戲概述:
1、玩家城池:可以移動設施、升級設施、新建設施、管理士兵、管理英雄。
2、關卡戰斗:可以派出士兵自動尋路***,可以控制英雄移動,***指定建筑,釋放技能。
3、戰略地圖通過迷霧遮罩,升級雷達,可以擴大地圖的可視范圍。
視頻鏈接:http://v.youku.com/v_show/id_XOTM0NzQ3NDQ4.html
【開發環境】
Cocos2d-x 3.4
Cocos Studio 1.6.0 (UI編輯器、動畫編輯器)
【一些重要的收獲】
1、分辨率適配問題
由于地圖比較大,可以通過拖動來顯示地圖的其他區域部分,所以分辨率的適配比較簡單。只要寬度或高度適配即可。
2、地圖的移動與縮放
可以參見這篇文章:http://cn.cocos2d-x.org/tutorial/show?id=1479
根據手指觸摸的數量,來判斷是移動還是縮放。
> 一根手指:移動地圖,實現比較簡單。
> 兩根或多根手指:看做兩根手指,縮放地圖。需要通過一定的公式來計算,縮放前和縮放后的坐標轉換。(具體參見上述文章)。
對于手指滑動后,地圖又具有慣性地減速移動:可以根據手指滑動的速度快慢,計算出一個加速度(其實可以通過觸摸事件onTouchMoved中Touch的getDelta()函數獲得),然后通過在update函數中進行減速計算。
縮放的前后坐標計算,如下圖所示:
3、玩家城池中,建筑的坐標定位
對于45°坐標,可以參照這篇文章:http://blog.sina.com.cn/s/blog_6807f539010103ce.html
由于城池中采用的是斜45°的2.5D視角,所以需要進行坐標的轉換操作。
先將城池地圖進行瓦片分割,分成一塊一塊區域。如下所示,其實可以看到地圖是一個個小方塊組成的。
4、關于建筑的觸摸移動
當建筑需要移動它的位置的時候,需要屏蔽地圖層的移動和縮放,不然你回發現你的建筑和地圖都在移動!!!
做法是:觸摸到建筑,進行移動時,其實cocos已經有了觸摸吞噬的函數
listener->setSwallowTouches(true);即可。
當然還有一種比較好的做法是:定義一個專門處理觸摸事件的觸摸層,來管理場景中所有元素的觸摸事件,并按照觸摸的優先級進行排序,然后再按照優先級進行分發觸摸響應事件(因為一般觸摸只會有一個事件作出響應,也就是說每次的觸摸只會有一個元素執行了觸摸事件)。
5、關于設施升級、時間點觸發某事件等一系列的響應事件
在設施進行升級、或者當到大某一時間點時,可能需要觸發一些任務響應事件。可以通過委托模式來處理,即在做某一事件時,給該事件委托一個函數(可以通過函數指針來實現)。然后當某一事件完成后,調用該委托函數(可以不指定為某一特定的函數,而是通過函數指針的形式來調用)。
另一種做法是:通過觀察者模式,即一個事件對某一消息進行訂閱,然后另一個事件在執行完后,發布該消息,然后第一個事件就接受到了消息,執行相應的處理函數。
例如:士兵***建筑時,士兵執行完***動作,然后建筑需要作出“扣血”這一事件。就可以通過委托函數來完成,即實現不知道需要執行哪個建筑的“扣血”事件。而是通過函數指針來調用對應士兵所***的那個建筑的“扣血”事件處理函數。
至于觀察者模式可參見:http://shahdza.blog.51cto.com/2410787/1611575
6、對于游戲中時間控制的問題
因為是一個城戰類的游戲,所以設施的升級是需要一定的時間的,比如升級需要10分鐘。還有采礦場每分鐘可以生產10個金幣等等,都是需要用到“時間”。
做法是:拿設施的升級操作舉例,在點擊對設施進行升級時,可以記錄一個升級時的“時間戳”,并存儲到數據庫的該設施的一個字段中,然后再游戲進行的過程中,只要不斷獲取當前時間的“時間戳”,然后減去之前記錄的點擊升級時的“時間戳”。差值即為從升級到目前過去了多少時間,然后就可以做一些列的操作了。
關于如何獲取時間戳,參見:
// 獲取時間戳 int GlobalManager::getTimeStamp() { timeval tm; gettimeofday(&tm, NULL); return tm.tv_sec; // 返回當前時間對應的時間戳,單位:秒 }
7、戰斗界面的AI(自動尋路、自動***)
也可以參見:http://cn.cocos2d-x.org/tutorial/show?id=1638
我的做法比較簡單,使用狀態機:移動、***、閑置、已陣亡。然后每隔0.5秒執行一次狀態轉換的操作。
首先將地圖分成一塊一塊,然后用二維bool矩陣來標記障礙物,然后控制士兵、英雄的移動。
> 對于士兵:設置定時器,每隔0.5秒執行一次動作。若士兵還未鎖定***目標,則遍歷設施,找到最近的設施作為目標。若士兵鎖定了***目標,則可以通過A*算法檢測上下左右、左上、右上、左下、右下八個方向的瓦片格子中,是空地,并且里目標建筑最近的,就將士兵往那個格子移動(至于距離:可以通過h函數來估計,我采用的是估計函數:曼哈頓距離,即x坐標之差的絕對值 + y坐標之差的絕對值),這樣士兵可以自動繞過障礙物。若目標設施在士兵的可***范圍內,則對設施進行***。
我為什么要嘗試每隔一定時間,檢測士兵的八個方向,離目標最近,然后移動過去呢?是因為如果士兵鎖定了目標后,然后執行完整的A*算法,計算出完整的移動路徑,這樣的操作是非常耗時的。對于很多個士兵同時執行完整的A*算法進行尋路,可能就會出現卡頓的現象。而我的做法正好避免了這樣的問題,將A*算法的每一步操作都均攤到每個0.5秒的時間。
> 對于英雄:通過觸摸來控制移動,和***某一目標。觸摸地圖某一位置,英雄移動的操作與士兵的自動尋路和自動***思路類似。
> 對于可***型建筑:設施定時器,每個0.5秒執行一次。遍歷我方士兵、英雄。若有士兵在建筑的可***范圍內,則***我方。
8、頭文件的管理
由于類和類之間不是獨立存在的,必然會有頭文件的相互引用問題,所以我就額外將所有的類的頭文件都放到一個public.h文件中,那么其他類只要引用"public.h"頭文件即可,而不需要考慮需要引用哪些哪些頭文件。
然后在 public.h文件開頭加上文件預編譯指令:這樣就可以保證頭文件不會被多次編譯。
#ifndef __Public_H__ #define __Public_H__ #endif
9、全局變量的管理
也是當獨放到一個頭文件中進行管理的:包含了圖片資源的路徑、一些全局變量、數據文件的路徑等。
10、CocosStudio的使用
本游戲用的時Cocos Studio 1.6.0版本。其實這個版本是已經非常強大了,不僅可以做界面UI,而已可以制作角色動畫。
使用方法:到官網學習。
11、數據的管理
寫了一個專門管理游戲數據的單例類DataManager。用于數據的加載、獲取、更新等操作。
對于表現層和控制層有哪些數據修改的請求操作,都通過DataManager進行管理,然后再重新繪制游戲的UI。
12、一些全局的輔助函數的管理
也是用了一個GlobalManager單例類來進行管理。提供游戲中的相關的輔助函數。
如:獲取最大最小值、地圖坐標與瓦片坐標的轉換、判斷一個點是否落在多邊形內、獲取時間戳、×××數據和字符串數據的轉換、場景的切換管理等功能。
【遇到的問題】
1、瓦片坐標與地圖坐標的轉換
計算相應的轉換公式。
2、兩頭文件相互引用
需要在類之前,對另一個類做類的聲明。
3、野指針問題
當兩個建筑都鎖定同一個士兵后,第一個建筑執行完***動畫,然后讓該士兵作出扣血事件,正好士兵血沒了,就要從圖層中移除。可是呢?第二個建筑也鎖定了該目標啊,執行玩***動畫后,調用該士兵的扣血事件,出現了異常。因為該士兵已被釋放。。。
解決方案:
(1)一直保留士兵,陣亡后,不從圖層中移除,而是將士兵隱藏。
(2)延遲士兵的移除操作。由于建筑是每個0.5秒尋找一次目標,然后對其進行***。那么我們只要在士兵陣亡后,用一個變量isDeath來標記士兵是否陣亡,然后建筑在遍歷士兵時,跳過isDeath=true的士兵,那么建筑在下一個0.5秒就不會再指向該士兵。那么士兵只要在陣亡后,標記isDeath=true,然后延遲1秒鐘后,調用remove()函數從圖層中移除,就不會出現野指針異常的問題。
(3)同樣也可以通過觀察者模式,建筑對士兵的陣亡消息進行訂閱,然后當士兵陣亡后,發布陣亡消息。建筑在接收到陣亡消息后,將鎖定的目標target指針置為空NULL,即可。
4、中文亂碼問題
使用UTF-8即可。
5、游戲AI問題
學習了A*算法。
6、還有其他一些小問題,已忘………………
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。