距離上一款游戲上線已經兩月有余,上線期的雞血退去后只留下無鞭的寂寞。所以就來開了個博客,通常一血會比較重要,經過一番深思熟慮,朕決定來總結下上款游戲里我的主要工作。本篇是系列篇之一。
名字其實起大了,說是一款通用框架,也就是我的一些感想。從零開始做一款游戲,第一款游戲,並且作為公司內部最早使用cocostudio做UI的項目,坑我們是踩的比較多的,自然想法也會多一些。
保守點說,項目百分之四十的工作量在UI上面。我進組的時候項目還是個demo,只有一個戰斗用的界面,並不成系統。然后發現隨着界面的增加,控制它們之間的跳轉實在是件麻煩事。一個很簡單的事,界面A跳轉到界面B,而C也可以跳轉到B,B界面上有一個返回按鈕,它的行為應該是啥?沒有系統的話只能二選一,意味着從C跳到B,再點返回鍵卻到了A界面。首先體驗很差,其次邏輯也不對。這里體現了程序員對所謂UI系統的一個需求:記錄界面跳轉棧。除此之外,想優雅地做UI內存控制也是離不開一個良好的系統的。下面就來詳述一下當初我設計的UI系統。
首先,我們來定義一下UI,我的想法是,一個界面用一個類管理,稱為一個UI,這些類繼承自共同的父類。需要引入並強化ui生存周期概念,主要相關方法如下:
a)oncreate()ui首次創建時調用的方法,通常可以在此讀取ui配置文件和紋理圖片;
b)onenter()從其他界面跳轉到此界面調用的方法,通常在此實現ui和后台數據的同步,恢復ui的cpu活動。
c)onleave()從此界面切到其他界面,通常在此使ui不再顯示,並根據需要停止其cpu活動
d)ondestory()銷毀此界面對象。從內存中銷毀對象,減小內存占用。
e)update()界面的實時更新。用於監視關聯數據,數據一旦變化需要實時顯示。由於此方法被頻繁調用,建議最小化之。
其次,根據我的理解,我把UI分成了幾個大類。分類的邏輯主要在於他們各自不同的行為,分類的結果最明顯地體現在繪制順序的不一樣,在cocos2dx中就是zorder不同。
a) 背景UI。很明顯,這類UI最早被繪制。它存在的主要原因是很多主要的界面會共用同一張圖作為背景,把這個圖抽出來單獨管理一方面可以節省資源,二來也可以統一做些花頭。這個UI來一個實例就全局夠用了。zorder最低。定義為UI_TYPE_BG。
b) 主UI。舉個例子,一般游戲都有個大廳,這個大廳就屬於主UI。這類UI的特點是同類UI同時只有一個可見。我在大廳選擇“出戰”,跳到了選關界面,這倆都是主UI,所以這時大廳界面就沒必要繪制了。zorder其次。定義為UI_TYPE_MAIN。
c) 常用UI。最常見的例子是玩家屬性條,顯示玩家的金幣、體力之類的。這種界面常駐GPU,大廳上會見到它,選關時候也會看到它,所以它的邏輯不同於上一類。它可以和其他UI同時顯示,zorder會比主UI至少高一層。而依據游戲的具體需求,不同的常用UI可能zorder也會不一樣,這就具體方案具體實現了。定義為UI_TYPE_CONSTANT。
d) 彈出框類UI。比如付費確認就是個彈出框。一般會是一個流程上的卡點,沒法繞過的。所以它出現的時候其他UI應該都不能用了,包括同為彈出框的其他UI。所以它的特點在於,和同類UI繪制不兼容,和其他類UI繪制兼容但操作不兼容。zorder比較高,應高於所有的常用UI。定義為UI_TYPE_POPUP。
e) 其他類UI。目前我遇到的是新手指引的界面。關於新手指引,后面打算另開一篇講講,也是個大坑。新手指引比較inba,zorder高於所有的UI,因為所有的UI都可能要指引。這類UI在管理層上邏輯並不復雜,因為通常是單例,基本可以套用主UI的邏輯。定義為UI_TYPE_OTHER。
然后管理器也需要來一個類UIMgr,最好是單例。嚴格來說,UI類對外部操作者不可見,程序員在UI類外部對UI進行操作都需要經過管理類的消息轉發。管理類的內部邏輯控制着UI的跳轉流程等等。例如,程序員只需要告訴UIMgr,需要進入某一個UI,傳入的參數只有UI的名字和必要的初始化參數,然后整個游戲的界面會變成什么樣就交給UIMgr內部黑盒處理。
從游戲UI設計的角度出發,最值得關心的是美術風格和玩家交互,但是從程序員的角度出發,應該考慮的是整個UI的系統性。難免會遇到奇葩需無法在現有系統中實現,這個時候解決辦法有兩種,一種是擴展系統,豐富系統功能,二是和UI設計者協調,有時候降低百分之十的效果預期會減少百分之八十的程序工作量,這種情況程序員應盡力去爭取。而最不該做的就是往系統里加各種判斷代碼,絲毫不顧系統性,增加維護成本不說,觀感也差。