1. 程式人生 > >使用DirectX打造遊戲GUI介面(二)

使用DirectX打造遊戲GUI介面(二)

本系列文章由zhmxy555(毛星雲)編寫,轉載請註明出處。 


hello,我們又如約相見了。:)

上一講中我們已經實現了一個簡單的GUI系統,顯示出了遊戲的GUI主選單頁面,而本篇文章的主要目的是在之前GUI系統的基礎上,實現GUI中多個頁面間的切換和返回,更具有實用意義。

首先依然是放出截圖吧,首先是主選單頁面:


【開始新遊戲】介面:

 

【載入遊戲】介面:

 

【選項】介面:

 

嗯,做出來的效果還是可圈可點的。

為了更好理解的這篇文章的內容,推薦大家先回去稍微瞄一下之前的那篇文章,這裡貼心的給出傳送門:

那麼,下面我們就繼續開始我們的革命吧,首先完成之前遺留下來的任務,講一下我們GUI系統的心臟——ProcessGUI。

一、核心函式ProcessGUI的講解

這個傳說中的ProcessGUI函式可謂是我們GUI系統中的最重要的一個函式,它渲染了整個GUI系統,同樣還為控制元件呼叫了回撥函式。它引數包括需要處理的GUI,表明滑鼠左鍵是否被按下的布林值,然後是以畫素為單位的滑鼠指標位置,以及指向處理控制元件時要用到的通用回撥函式的指標。另外我們知道,一般而言對於回撥函式的話,需要兩個引數,一個是控制元件的ID,另一個就是控制元件的狀態。根據描述,函式原型就躍然紙上了:

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. void ProcessGUI(D3DGUIClass *gui, boolLMBDown, int mouseX, int mouseY, void(*funcPtr)(int id, int state)):  

函式體寫法方面的話,首先我們獲取了D3D物件,渲染了背景圖。因為顧名思義,他是背景圖,就應該顯示在各控制元件的最下方,所以我們需要在繪製其他控制元件之前繪製它,這樣就可以在它之上隨心所欲的繪製其他控制元件了。第一部分的程式碼寫起來就是這樣:

[cpp]
 view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. if(!gui)return;  
  2.        LPDIRECT3DDEVICE9device = gui->GetD3dDevice();  
  3.        if(!device)return;  
  4.        //繪製背景
  5.        GUICONTROL*Background = gui->GetBackground();  
  6.        LPDIRECT3DVERTEXBUFFER9bdBuffer = gui->GetBackgroundBuffer();  
  7.        //已經創建出的東西才繪製,所以來個if
  8.        if(gui->IsBackgroundUsed()&& Background && bdBuffer)  
  9.        {  
  10.                  device->SetTexture(0,Background->m_Background);  
  11.                  device->SetStreamSource(0,bdBuffer, 0, sizeof(GUIVERTEX));  
  12.                  device->SetFVF(D3DFVF_GUI);  
  13.                  device->DrawPrimitive(D3DPT_TRIANGLESTRIP,0, 2);  
  14.                  device->SetTexture(0,NULL);  
  15.        }  

因為我們GUI系統目前就只和二維空間打交道,那麼在渲染GUI時,可以避免考慮深度測試這方面的問題。函式接下來要做的就是迴圈控制元件列表,並按照每個控制元件的型別對其加以渲染。在迴圈語句中有一個switch語句,它是用來檢查正在處理的控制元件型別的。若是靜態文字控制元件,就獲取這個文字使用的D3D字型物件,設定一下文字位置,並且呼叫DrawText來顯示文字。那麼程式碼寫起來就是這樣:

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. //用來顯示文字的物件
  2.          LPD3DXFONTpFont = NULL;  
  3.          RECTfontPosition = {0, 0, (long)gui->GetWindowWidth(),  
  4.                    (long)gui->GetWindowHeight()};  
  5.          //建立一個頂點快取物件用於按鈕的渲染
  6.          LPDIRECT3DVERTEXBUFFER9pBuffer = NULL;  
  7.          intstatus = UGP_BUTTON_UP;  
  8.          //一個迴圈,用於各種控制元件的渲染
  9.          for(inti = 0; i < gui->GetTotalControlNum(); i++)  
  10.          {  
  11.                    //獲取當前控制元件
  12.                    GUICONTROL*pControl = gui->GetGUIControl(i);  
  13.                    if(!pControl)continue;  
  14.                    //根據不同的型別做不同的操作
  15.                    switch(pControl->m_type)  
  16.                    {  
  17.                    caseUGP_GUI_STATICTEXT:  
  18.                             //這種情況下獲取字型物件
  19.                             pFont= gui->GetFont(pControl->m_listID);  
  20.                             if(!pFont)continue;  
  21.                             //設定文字位置
  22.                             fontPosition.left= pControl->m_xPos;  
  23.                             fontPosition.top= pControl->m_yPos;  
  24.                             //顯示文字
  25.                             pFont->DrawText(NULL,pControl->m_text, -1, &fontPosition,  
  26.                                      DT_LEFT,pControl->m_color);  
  27.                             break;  

處理按鈕的話,工作量就稍微大一點了。首先我們得到當前按鈕使用的頂點快取指標,這就和獲取靜態文字控制元件使用的D3D字型物件指標差不多。然後呢,啟用透明混合處理功能,這樣按鈕可以有透明背景,可以為按鈕增添些許效果,在設計按鈕影象時就可以有更多的選擇。接下來就順勢設定一下按鈕狀態。有了按鈕狀態的話,就可以確定要繫結的紋理了,我們使用if語句測試滑鼠指標的位置是否落在按鈕畫素內,如果按鈕的四個頂點的位置把滑鼠指標的位置包含在其中了,那麼就可以知道滑鼠在按鈕的區域裡面。

若滑鼠指標落在按鈕區域中並且滑鼠左鍵被按下,我們就知道玩家正在單擊按鈕,就把按鍵狀態設成UGP_BUTTON_DOWN。如果這都不滿足的話,那麼玩家就只是把滑鼠指標放在了按鈕之上,並沒了點選按鈕,就else設成UGP_BUTTON_OVER。根據我們的思路,程式碼就這樣寫:

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. case UGP_GUI_BUTTON:  
  2.                           status= UGP_BUTTON_UP;  
  3.                           //獲取按鈕所對應的頂點快取物件
  4.                           pBuffer= gui->GetVertexBuffer(pControl->m_listID);  
  5.                           if(!pBuffer)continue;  
  6.                           //設定紋理的alpha透明選項
  7.                           device->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);  
  8.                           device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);  
  9.                           device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);  
  10.                           //檢查滑鼠是否懸停或者點選了按鈕
  11.                           if(mouseX> pControl->m_xPos && mouseX < pControl->m_xPos +pControl->m_width &&  
  12.                                    mouseY> pControl->m_yPos && mouseY < pControl->m_yPos +pControl->m_height)  
  13.                           {  
  14.                                    if(LMBDown)status = UGP_BUTTON_DOWN;  
  15.                                    elsestatus = UGP_BUTTON_OVER;  
  16.                           }  

接著就是根據不同的滑鼠和按鈕之間纏綿悱惻的狀態來準備不同的紋理圖繫結上去了:

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. if(status== UGP_BUTTON_UP) device->SetTexture(0, pControl->m_upTex);  
  2. if(status== UGP_BUTTON_OVER) device->SetTexture(0, pControl->m_overTex);  
  3. if(status== UGP_BUTTON_DOWN) device->SetTexture(0, pControl->m_downTex);<span style="font-family: 'Microsoft YaHei';">                        </span>  

一切準備就緒,然後開始麻溜的進行渲染,關閉上alpha混合.。

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. //萬事俱備,開始渲染按鈕
  2.                         device->SetStreamSource(0,pBuffer, 0, sizeof(GUIVERTEX));  
  3.                         device->SetFVF(D3DFVF_GUI);  
  4. 相關推薦

    使用DirectX打造遊戲GUI介面

    本系列文章由zhmxy555(毛星雲)編寫,轉載請註明出處。  hello,我們又如約相見了。:) 上一講中我們已經實現了一個簡單的GUI系統,顯示出了遊戲的GUI主選單頁面,而本篇文章的主要目的是在之前GUI系統的基礎上,實現

    使用DirectX打造遊戲GUI介面

    這類遊戲所要模仿的物件就是HUD這個概念的來源的地方,所以駕駛模擬類遊戲HUD設計的原則也就變得非常簡單而直接:儘可能的去重現模擬物件的原始HUD就可以了。當然根據遊戲模擬真實的程度不同,再現真實HUD設計的程度也有所區別。HUD的設計始終存在一個如何抽取最重要的資訊提示玩家的問題,過於模擬的遊戲HUD設計將

    【Visual C++】遊戲開發五十六 淺墨DirectX教程十三 打造遊戲GUI介面

    眾所周知,GUI是遊戲中不可缺少的元素,這篇文章中,我們首先了解了遊戲GUI介面的知識與相關概念,然後一起設計了一個封裝好GUI圖形介面的C++類。這個類有著非常強的擴充套件性,使用也是極其方便,很適合二次開發。 先看一張實現的效果圖吧: 其中的背景音樂,遊戲圖

    塔防遊戲學習日記之朝敵人發射子彈

    one for component targe instant .cn times code 至少   檢測到炮塔內敵人進入以後,當然下一步就是要向他們發射子彈。   接下來我們來做朝敵人發射子彈的相關操作。   分析一下,要向敵人發射子彈,需要有攻擊速度,簡單的計時器,子

    遊戲開發經驗談:對戰類全球服遊戲的設計與實現

    bbr tro 機房 產品 sql 服務器 通過 簡單 自己實現 上篇文章《遊戲開發經驗談(一):遊戲架構裏隱藏的五個坑及其應對方案》,我們主要講解了遊戲架構設計當中隱藏的一些坑及其應對方案,錯過的小夥伴可以點擊鏈接回溯之前的內容。本期內容,將會重點介紹對戰類全球服遊戲的設

    限流和降級 | 如何打造平臺穩定性能力

    監控系統 兩個 服務業 流程 成功 ron href 統計 整體 摘要: 上一期我們談到了阿裏巴巴早期是通過通過在 Nginx 上實現的擴展組件TMD(taobao missile defense淘寶×××防禦系統)實現了接入層限流的主要工作,TMD系統可通過域名類限流、c

    如何快遞打造直播----應用篇

    轉載請註明出處:http://blog.csdn.net/xiaoyuan511 已經記不起上次寫部落格是在什麼時間了,真是對不起了。這大半年也不知道自己在幹什麼,說在學習,可是學的東西在實際工作因為沒有用到,很快又忘記了。可能做的最大的事就是把極客導航更新了吧,希望更為大

    HTML+Javascript製作拼圖小遊戲詳解

    上一篇我們說了網頁的基本佈局。接下來將為大家帶來具體的實現方法。 拼圖通表格來實現,做一個方形的表格,改變其大小使之如圖所示。 試想一下如果我們將一張圖片剪成6張分別放入對應位置,然後再把它打亂,這樣就可以進行拼圖了。 可是,將圖片放入和打亂圖片倒是不難,可想要實現移動圖片,這就有一點麻煩了。 不

    Java抽象類和介面

    ***************************介面********************************* 一.why 需求一直不變的時候可以不使用介面, 需求經常發生改變推薦使用介面... 軟體產品中需求會經常改變,所以一般都要使用介面... 體現了可維護、可擴充套件的優點 二.

    Java GUI程式設計

    **********************網格佈局 GridLayout********************** 類似於表格一樣,可以設定一個 幾行幾列的表格 小技巧(讓兩個元件垂直排列的小技巧): 一個元件放到邊框佈局的北邊,另一個元件放到中間 演示程式碼: package com.awt.

    freeswitch GUI介面portal

    1、控制檯 載入模組 load mod_xml_rpc 2、ip:8080/portal 進行登入  賬號 : freeswitch  密碼 : works    讓模組隨著freeswitch啟動進行載入  /usr/local/freesw

    ServletConfig介面

    研究javax.servlet.ServletConfig介面:     1、javax.servlet.ServletConfig是介面     2、Apache Tomcat伺服器實現了Servlet規範,Tomcat伺服器專門寫了一個ServletCon

    Java——Set集合(介面)___TreeSet用法

    Set(介面)集合:          TreeSet類(底層是二叉樹),能保證有序,用來對元素進行排序,能保證元素的唯一          使用方式:          1.自然順序:TreeSet類的add()方法中會把存入的物件提升為Comparable型別      

    移動遊戲ui設計--遊戲世界的基本法則

    遊戲世界的基本法則遊戲體驗的層次感很重要,製作一款趣味性強,宗旨明確的遊戲並不簡單。 l  風格統一性;要先明白遊戲的game genres,因為遊戲型別與風格密切聯絡。常見遊戲型別有:動作類、冒險類、模擬類、角色扮演類、休閒類和其他類。由不同的遊戲風格又可以將其風格概括為兩個大類:寫實和卡

    Django+xadmin打造線上教育平臺

    目錄 程式碼 線上演示 三、xadmin後臺管理 3.1.xadmin的安裝 django2.0的安裝(原始碼安裝方式): https://github.com/sshwsfc/xadmin/tree/django2 把zip檔案放到pip目錄下,執行下面命令安裝

    JAVA 貪吃蛇小遊戲分論

    在分論(一)討論了貪吃蛇和隨機點的設計,擋在窗體中定義好貪吃蛇和隨機點,那麼,最關鍵的問題是如何定義貪吃蛇的移動,以及當碰到隨機點以後會發生什麼? 貪吃蛇的移動說白了是座標的變化,如何控制座標變化呢?有兩個關鍵點需要考慮,方向和速度。第一,移動的控制,即外界通過什麼方式來控制貪吃蛇的移動方向

    python 使用tornadio書寫介面-非同步呼叫介面

    最近看了一下tornadio非同步呼叫的功能,做一個小總結,ps:有一些很好的文章我會把連結放到最後,供大家參考。 簡單說一下我理解的同步和非同步的概念,同步和非同步指的呼叫方而言就是http請求中對應request。 同步:是我呼叫一個介面,服務端要做處理,處理完成後給

    Hive使用者介面—使用Hive JDBC驅動連線Hive操作例項

    問題導讀:         1、Hive提供了哪三種使用者訪問方式?         2、使用HiveServer時候,需要首先啟動哪個服務?         3、HiveServer的啟動命令是?         4、HiveServer是通過哪個服務來提供遠端JDBC訪

    Unity遊戲設計模式觀察者模式Observer Pattern

            最近看遊戲設計模式,當看到觀察者模式時被搞得雲裡霧裡的,什麼觀察者,被觀察者,抽象觀察者,抽象被觀察者。聽著這些詞就覺得可怕,其實理解以後還是比較簡單的。         當我們玩遊戲時,經常會出現一些事件,而這個事件可能會影響到許多個模組時就可以用到觀察者

    Java學習之道:彈球遊戲分步解析——讓小球飛

    之前跟大家說要把事件監聽器和多執行緒分開來講,不過之後發現事件監聽器要涉及到很多小球運動的操作,所以,決定將兩個知識點合起來說,這樣會更便於大家理解: 實現小球在我們所繪製的窗體上運動就必須要用到多執行緒;讓小球類繼承Thread類,再重寫void run(){}方法即可;