如何為我的游戲實現一個UI系統,這個問題我想了很久,不過我現在可不像開始的時候那樣一點思路也沒有。如果你也被這個問題所困擾,我十分樂意與你分享這幾天來的學習成果。嘿嘿,我是不是有點得意忘形了?
在開始之前,我要提醒你,學而不思則惘。在看這篇文章的時候,請時刻保持頭腦清醒,如果有什么不太明白的話,請停下一兩分鐘,好好想想,這篇文章可不是囫圇吞棗就能看懂的哦!此外這篇文章是建立在部分實例和猜測的基礎上的,可能存在著大量的不科學的想法和嚴重的錯誤,如果你在實踐的過程中出現了問題歡迎提問,如果你發現了其中的錯誤請你指出來,如果將來你發現被誤導了(當然我會盡力減小這種可能),請不要埋怨,因為是否繼續往下看是你自己的決定。
1、窗口
UI系統的表現形式是什么?在開始前我們有必要弄清這個問題。
我們需要對話框、按鈕、單選按鈕、復選按鈕、滾動條、下拉列表……好了好了,想不到你一口氣竟能說出這么多種窗口。是的,這些都是不同形式的窗口,UI系統正是靠著形形色色的窗口展示自己,請記住這一點。如果你還是不明白,就看一看MSDN中的Hierarchy Chart。
2、理解windows的UI系統
windows這樣一套經典的圖形操作系統,我如果不拿它做例子,實在是有點兒對不住比爾大叔啊。
窗口都是矩形的,不要跟我說不規則窗口,其實那也是一個矩形的,只不過有些地方沒有畫而已。既然是矩形,只要知道它的長和寬(Width,Height,有點兒不一樣是吧?windows里叫寬和高),它就確定了。然后,你把它放在某個位置上,所以它又有了坐標(xPos,yPos)。你的UI系統至少也要有這些數據,不然就沒法畫了。
然后是各式各樣的事件,當鼠標經過的時候,按鈕變亮了;當你按下Alt+F的時候,彈出了一個菜單。不管在windows里是哪個設備驅動把這些信息告訴了UI系統,我們的確需要它,不是嗎?
一個菜單被按下然后一個對話框彈了出來,是誰的結果?是鼠標嗎?怎么可能!當然是UI系統干的。UI系統不僅要接受各種輸入設備的信息改變相應的外觀,它還要根據不同的操作產生消息。菜單按下時,windows會主動地往消息隊列里發送一個WM_COMMAND消息。至于對話框是否會彈出來,就要看你是否對這個消息進行處理了。
還有別的什么嗎?
當然有啦,只是我也不很清楚,畢竟才研究了三四天嘛。不過我可以告訴你是什么:那么多不同類型的窗口,windows是怎么區分的?這個問題很關鍵啦,窗體如何繪制,事件如何激發全都需要判斷的。比如說一個普通按鈕和一個單選按鈕,一個按下之后要彈起來,另一個要有一個圓點,明顯的不同。既然都是窗口,windows是怎么做到的呢?我在winuser.h里面看到了大量關于STYLE的宏,我猜是用了CASE判斷,可是為每一個窗口都作判斷也太麻煩了吧,還在研究中。。。
3、窗口類的封裝
封裝是為了更好的使用,但不是必需的。就像使用MFC我們可以方便開發項目。(不要跟我討論你對MFC的感情,那是你自己的事)然而如果沒有他,只用SDK我們一樣可以完成上司的任務。但是為了方便我建議你這樣做,封裝你的窗口類。我沒有對此作太多的研究,我想把更多的時間放到研究UI系統本身上。如果你想了解得更多,請看這里http://blog.csdn.net/mythma
4、消息映射及命令繞行
和封裝窗口類一樣,這也只是一個輔助性的工作。這也是MFC的做法,如果你的游戲不需要如此復雜的方法,或是你對此方法有成見的話就不要做了。也許,我真的有點偏離我的初衷,不像是在給我的游戲實現一個UI系統了。如果你想為類似DOS的系統添加一個GUI的話,嘿嘿,X-Window那樣子的。按本文的UI系統做也許會有點小用。
對于消息映射和命令繞行,我說不好,看了兩天《深入淺出MFC》,才稍微有點明白,建議你自己去看。我只說一點不同之處,游戲中MFC的方法不是完全適用的。MFC是一個應用程序框架,MFC命令繞行的過程控制的是程序的全部,而游戲的UI系統只是一個輔助部分,不是全部,甚至可以去掉(我是說做到游戲里去,我猜95仙劍的菜單就是和游戲一體的)。UI系統要根據鼠標鍵盤做出不同的反應,繪制不同的界面,它又不是程序的全部,所以你需要把每一個可用(有用)的消息都傳給UI系統。(不一定是全部的消息,比如說我的UI只使用鼠標操作,那就只傳遞WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE、WM_LBUTTONDBLCLK等等)
while(1)
{
if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)
{
if(!GetMessage(&msg,NULL,0,0))
break;
if(!TranslateAccelerator(msg.hwnd,hAccelTable,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 在這里添加你向UI系統傳遞消息的代碼
UI_DecipherMessage(&msg);
}
else
{
// 在這里添加你游戲的主要邏輯代碼
GameMain();
}
}
然后,做一個僅使用在UI系統內部的消息映射和命令繞行,它處理的是UI系統自己產生的消息,或是改變一些窗口的顯示與關閉,或是向游戲主要邏輯做出如使用物品、退出游戲之類的信號。是的,UI系統需要自己產生很多消息,不要指望windows會主動因為你的控件被按下而向消息隊列里傳送WM_COMMAND消息,你得自己做這些,使用PostMessage函數就可以了。有時候工作會更多,因為你面對的是windows的消息隊列和UI系統自身的消息隊列。
5、一個例子
HOHOv5中的UI系統作為這篇文章的例子再合適不過了,可以說我的思路可能是被它干擾了。
在下一篇中,我可能會講講本文未能說清楚的問題和一個不用消息映射及命令繞行的實例。
參考:
(1)HOHOv5的UI系統頭文件(沒辦法,我沒有任何一個版本的源文件,也沒厚著臉皮去找人家要。嘿嘿,關鍵是沒法要。寫這篇文章的時候我的網還沒有辦下來,怎么到我這里就預留接口不足,氣死了)
(2)《深入淺出MFC》第一章的訊息映射的雛形、第三章的訊息映射和命令繞行、第九章的全部
(3)MSDN和winuser.h
(4)窗口之父CXWnd的封裝
不含病毒。www.avast.com |
留言列表