在過去的8年里,我經(jīng)過數(shù)次失敗的GUI系統(tǒng)設(shè)計(jì)經(jīng)歷,最終找到了一種算是可以的方案。這個(gè)方案使用一種類似MVC的架構(gòu)。主要有以下幾個(gè)大的部分:
【sprite系統(tǒng)】
sprite是一個(gè)從古老的游戲中一直演化過來的概念,而在這里,它代表了屏幕上的一個(gè)次元(層)中所有可見元素。
它描述了一個(gè)屏幕上的矩形,以及和其他矩形的關(guān)系。
它具有自己的更新和繪制方法。
它具有自己的各種特性,比如可拖動(dòng),比如事件冒泡。
同時(shí),它還有一個(gè)稱為控制器的東西,這個(gè)東西會(huì)在創(chuàng)建或者attach的時(shí)候?qū)prite進(jìn)行修改或者初始化。會(huì)處理sprite的輸入事件,并可以接管sprite的繪圖處理。
【UI元素】
UI元素是sprite的控制器接口的實(shí)現(xiàn)。并且會(huì)在初始化時(shí)去創(chuàng)建sprite,以達(dá)到顯示的目的。
一個(gè)UI元素就代表一個(gè)UI控件,比如一個(gè)編輯框,或者是一個(gè)combobox。
每個(gè)UI元素上都有數(shù)個(gè)事件的插槽,應(yīng)用程序可以通過向這些插槽插入事件處理來關(guān)注UI元素。
【UI腳本】
UI元素的插槽不僅可以插入一個(gè)事件處理,還可以插入一個(gè)UI腳本的方法索引。
而腳本系統(tǒng)和腳本方法索引,都是接口和無特定指向意義的數(shù)值類型,方便腳本擴(kuò)展。
【引擎接口】
因?yàn)閁I系統(tǒng)中會(huì)用到繪圖,貼圖,聲音,為了通用性,這些都被抽象為接口,以便于不同引擎的支持。
但是這個(gè)里面有一點(diǎn)非常重要,就是一定不要依賴于某個(gè)特定引擎或者平臺(tái)的特性進(jìn)行接口設(shè)計(jì),那會(huì)讓你束手束腳。
【資源管理】
因?yàn)閁I系統(tǒng)中會(huì)涉及到比較多資源,所以,所有資源都被統(tǒng)一管理起來。通過字符串來進(jìn)行資源索引。返回的是資源的接口指針。
在資源管理內(nèi)部,對(duì)每種資源都有一個(gè)緩沖池。當(dāng)然只做按名字緩沖,畢竟比較深層次的資源緩沖還要依賴引擎接口來完成。
資源里主要有以下幾種:圖像(貼圖組合動(dòng)畫),貼圖,聲音,字體。
【文字繪制】
文字繪制,由字體資源和繪圖引擎接口共同來完成。
字體資源里有個(gè)中間件,用來管理字體的緩存,目前是采用256級(jí)灰度點(diǎn)陣來存儲(chǔ),在各種繪圖引擎和平臺(tái)中都可以方便的轉(zhuǎn)化為屏幕圖元,并且還有灰度來保障邊緣混淆的正確顯示。
【關(guān)于繪圖系統(tǒng)】繪圖系統(tǒng)中,GUI的需求主要是 貼圖, 繪制簡單的矩形邊框矩形填充, 繪制線條, 裁剪。
GDI繪圖,一開始就被放棄了,因?yàn)樗恼麄€(gè)系統(tǒng)的繪圖特性過多,會(huì)導(dǎo)致關(guān)注點(diǎn)的分散。為了替代GDI繪圖,我實(shí)現(xiàn)了一套內(nèi)存位圖的繪圖庫。不過最終這個(gè)庫還是會(huì)把結(jié)果丟到GDI的HDC上,只是中間過程里,都是在內(nèi)存中進(jìn)行圖像的各種混合。
DX和OGL,因?yàn)檫@兩個(gè)都可以支持貼圖,所以實(shí)現(xiàn)UI系統(tǒng)需要的接口完全沒有問題。在實(shí)際GUI的編碼和測試中,我使用HGE這個(gè)DX的封裝接口來間接實(shí)現(xiàn)了UI系統(tǒng)所需的繪圖接口。
【數(shù)據(jù)源】UI系統(tǒng)里,每個(gè)UI元素都是從數(shù)據(jù)源中進(jìn)行讀取并創(chuàng)建的。
數(shù)據(jù)源是一個(gè)純虛接口的形式,在實(shí)際編碼和測試中,我使用的是XML作為數(shù)據(jù)源。
XML既有良好的可讀性,又易于程序處理。非常適合在這里作為數(shù)據(jù)源。
【UI編輯器】
相應(yīng)的,生成數(shù)據(jù)源的部分,就是靠UI編輯器。
UI編輯器本身也是通過UI系統(tǒng)實(shí)現(xiàn)的。
UI編輯器主要包括幾個(gè)部分:布局編輯器、貼圖撿取、屬性編輯。其中布局編輯器這里,每個(gè)控件的繪制仍舊調(diào)用的是它自身的繪圖方法,不過為了防止觸發(fā)控件本身的事件,我用一個(gè)控件編輯容器樹,代替了原來的控件元素樹,樹結(jié)構(gòu)還是使用原有的結(jié)構(gòu),控件被作為空間編輯容器的子元素。
【歷史】2002年 第一版UI系統(tǒng) 繪圖使用DIRECTDRAW,采用UI元素和UI視覺元素統(tǒng)一的方法,采用一棵樹進(jìn)行繪制和UI自身的管理。沒有數(shù)據(jù)源,沒有編輯器,沒有腳本系統(tǒng),完全試驗(yàn)品。失敗原因:UI元素的設(shè)計(jì)問題,以及架構(gòu)不完善。
2005年 第二版UI系統(tǒng) 繪圖采用D3D,采用UI元素和UI視覺元素統(tǒng)一的方法,采用一棵樹進(jìn)行繪制和管理。無數(shù)據(jù)源,無編輯器,無腳本系統(tǒng),有事件處理插槽,在客戶端進(jìn)行了小規(guī)模的使用。
2008年 第三版UI系統(tǒng) 繪圖采用抽象接口,有GDI(內(nèi)存位圖)和D3D實(shí)現(xiàn)。采用UI元素和UI視覺元素統(tǒng)一的方法,一棵樹繪制和管理。有數(shù)據(jù)源,無編輯器,無腳本系統(tǒng),僅在開發(fā)和測試環(huán)境內(nèi)進(jìn)行了使用。失敗原因:糾結(jié)在UI元素布局的管理上,后發(fā)現(xiàn)是UI元素的設(shè)計(jì)有問題。
2009年 第四版UI系統(tǒng) 繪圖采用抽象接口,有GDI(內(nèi)存位圖)和D3D(HGE),采用UI元素和UI視覺元素統(tǒng)一方法,一棵樹繪制和管理,有數(shù)據(jù)源,有編輯器。失敗原因:UI元素和視覺元素統(tǒng)一的方法,給UI元素的管理和UI元素的邏輯實(shí)現(xiàn)帶來很大限制。
2011年 第五版UI系統(tǒng) 繪圖采用抽象接口,有GDI(內(nèi)存位圖)和D3D(HGE),采用UI元素和UI視覺元素分開的方法,分為一顆邏輯樹,一顆視覺樹。數(shù)據(jù)源仍舊用XML,用第四版的編輯器實(shí)現(xiàn)方式。