【Visual C++】游戏开发五十七 浅墨DirectX教程二十四 打造游戏GUI界面(二)

本文深入讲解游戏GUI系统的核心函数ProcessGUI,演示如何实现GUI页面间的切换及返回功能,包括渲染背景、文本显示、按钮状态判断及纹理绑定等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               



 本系列文章由zhmxy555(毛星云)编写,转载请注明出处。  

 文章链接: http://blog.csdn.net/poem_qianmo/article/details/16922703

 作者:毛星云(浅墨)    邮箱: happylifemxy@163.com  



hello,我们又如约相见了。:)

上一讲中我们已经实现了一个简单的GUI系统,显示出了游戏的GUI主菜单页面,而本篇文章的主要目的是在之前GUI系统的基础上,实现GUI中多个页面间的切换和返回,更具有实用意义。


首先依然是放出截图吧,首先是主菜单页面:


 

【开始新游戏】界面:

 

【载入游戏】界面:

 


【选项】界面:

 


嗯,做出来的效果还是可圈可点的。


为了更好理解的这篇文章的内容,推荐大家先回去稍微瞄一下之前的那篇文章,这里贴心的给出传送门:



【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)


那么,下面我们就继续开始我们的革命吧,首先完成之前遗留下来的任务,讲一下我们GUI系统的心脏——ProcessGUI。







一、核心函数ProcessGUI的讲解


 

 

这个传说中的ProcessGUI函数可谓是我们GUI系统中的最重要的一个函数,它渲染了整个GUI系统,同样还为控件调用了回调函数。它参数包括需要处理的GUI,表明鼠标左键是否被按下的布尔值,然后是以像素为单位的鼠标指针位置,以及指向处理控件时要用到的通用回调函数的指针。另外我们知道,一般而言对于回调函数的话,需要两个参数,一个是控件的ID,另一个就是控件的状态。根据描述,函数原型就跃然纸上了:

void ProcessGUI(D3DGUIClass *gui, boolLMBDown, int mouseX, int mouseY, void(*funcPtr)(int id, int state)):


函数体写法方面的话,首先我们获取了D3D对象,渲染了背景图。因为顾名思义,他是背景图,就应该显示在各控件的最下方,所以我们需要在绘制其他控件之前绘制它,这样就可以在它之上随心所欲的绘制其他控件了。第一部分的代码写起来就是这样:

 

  if(!gui)return;          LPDIRECT3DDEVICE9device = gui->GetD3dDevice();         if(!device)return;          //绘制背景         GUICONTROL*Background = gui->GetBackground();         LPDIRECT3DVERTEXBUFFER9bdBuffer = gui->GetBackgroundBuffer();          //已经创建出的东西才绘制,所以来个if         if(gui->IsBackgroundUsed()&& Background && bdBuffer)         {                   device->SetTexture(0,Background->m_Background);                   device->SetStreamSource(0,bdBuffer, 0, sizeof(GUIVERTEX));                   device->SetFVF(D3DFVF_GUI);                   device->DrawPrimitive(D3DPT_TRIANGLESTRIP,0, 2);                   device->SetTexture(0,NULL);         }

因为我们GUI系统目前就只和二维空间打交道,那么在渲染GUI时,可以避免考虑深度测试这方面的问题。函数接下来要做的就是循环控件列表,并按照每个控件的类型对其加以渲染。在循环语句中有一个switch语句,它是用来检查正在处理的控件类型的。若是静态文本控件,就获取这个文本使用的D3D字体对象,设置一下文本位置,并且调用DrawText来显示文本。那么代码写起来就是这样:

//用来显示文本的对象         LPD3DXFONTpFont = NULL;         RECTfontPosition = {0, 0, (long)gui->GetWindowWidth(),                   (long)gui->GetWindowHeight()};          //创建一个顶点缓存对象用于按钮的渲染         LPDIRECT3DVERTEXBUFFER9pBuffer = NULL;         intstatus = UGP_BUTTON_UP;          //一个循环,用于各种控件的渲染         for(inti = 0; i < gui->GetTotalControlNum(); i++)         {                   //获取当前控件                   GUICONTROL*pControl = gui->GetGUIControl(i);                   if(!pControl)continue;                    //根据不同的类型做不同的操作                   switch(pControl->m_type)                   {                   caseUGP_GUI_STATICTEXT:                            //这种情况下获取字体对象                            pFont= gui->GetFont(pControl->m_listID);                            if(!pFont)continue;                             //设置文字位置                            fontPosition.left= pControl->m_xPos;                            fontPosition.top= pControl->m_yPos;                             //显示文字                            pFont->DrawText(NULL,pControl->m_text, -1, &fontPosition,                                     DT_LEFT,pControl->m_color);                            break;


处理按钮的话,工作量就稍微大一点了。首先我们得到当前按钮使用的顶点缓存指针,这就和获取静态文本控件使用的D3D字体对象指针差不多。然后呢,启用透明混合处理功能,这样按钮可以有透明背景,可以为按钮增添些许效果,在设计按钮图像时就可以有更多的选择。接下来就顺势设置一下按钮状态。有了按钮状态的话,就可以确定要绑定的纹理了,我们使用if语句测试鼠标指针的位置是否落在按钮像素内,如果按钮的四个顶点的位置把鼠标指针的位置包含在其中了,那么就可以知道鼠标在按钮的区域里面。

若鼠标指针落在按钮区域中并且鼠标左键被按下,我们就知道玩家正在单击按钮,就把按键状态设成UGP_BUTTON_DOWN。如果这都不满足的话,那么玩家就只是把鼠标指针放在了按钮之上,并没了点击按钮,就else设成UGP_BUTTON_OVER。根据我们的思路,代码就这样写:

 

  case UGP_GUI_BUTTON:                            status= UGP_BUTTON_UP;                             //获取按钮所对应的顶点缓存对象                            pBuffer= gui->GetVertexBuffer(pControl->m_listID);                            if(!pBuffer)continue;                             //设置纹理的alpha透明选项                            device->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);                            device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);                            device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);                             //检查鼠标是否悬停或者点击了按钮                            if(mouseX> pControl->m_xPos && mouseX < pControl->m_xPos +pControl->m_width &&                                     mouseY> pControl->m_yPos && mouseY < pControl->m_yPos +pControl->m_height)                            {                                     if(LMBDown)status = UGP_BUTTON_DOWN;                                     elsestatus = UGP_BUTTON_OVER;                            }

接着就是根据不同的鼠标和按钮之间缠绵悱恻的状态来准备不同的纹理图绑定上去了:

if(status== UGP_BUTTON_UP) device->SetTexture(0, pControl->m_upTex);if(status== UGP_BUTTON_OVER) device->SetTexture(0, pControl->m_overTex);if(status== UGP_BUTTON_DOWN) device->SetTexture(0, pControl->m_downTex);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值