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

本文介绍了游戏GUI界面的重要性和设计概念,通过实例展示了如何使用Visual C++和DirectX打造游戏GUI系统,包括状态显示界面(HUD)的设计和按钮控件的实现。文章提供了详细的代码和游戏截图,适合初学者入门。
摘要由CSDN通过智能技术生成
               


 

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

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

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


 

众所周知,GUI是游戏中不可缺少的元素,这篇文章中,我们首先了解了游戏GUI界面的知识与相关概念,然后一起设计了一个封装好GUI图形界面的C++类。这个类有着非常强的扩展性,使用也是极其方便,很适合二次开发。

先看一张实现的效果图吧:



其中的背景音乐,游戏图标和背景图片都出自育碧公司的招牌式大作《刺客信条》。

程序的窗口大小已经被浅墨调成了1366 x768,现阶段比较流行的笔记本分辨率尺寸(其实真的想吐槽这个奇葩万年不变的电脑屏幕分辨率,在如今的后PC时代。手机屏幕都开始对1920 x1080的分辨率不满足了。。。。)


嗯,开始正文吧。

 


 


一、UI和GUI的概述


首先我们看一下UI的比较正统的定义:用户界面(User Interface,简称UI,亦称使用者界面)是系统和用户之间进行交互和信息交换的媒介,它实现信息的内部形式与人类可以接受形式之间的转换。

用户界面是介于用户与硬件之间,为彼此之间交互沟通而设计的相关软件,使得用户能够方便有效地去操作硬件以达成双向之交互,完成所希望的工作,用户界面定义广泛,包含了人机交互与图形用户界面,凡参与人类与机械的信息交流的领域都存在着用户界面。

 

而GUI的正统定义是:图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面。与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受。

 

我们知道,在游戏中,能够和游戏玩家进行交互是至关重要的。这样的交流可以是文本形式的,视觉显示,声音信号等等。而对于视觉显示而言,绝大多数游戏毋庸置疑就是用图形用户界面(GUI)来和游戏玩家进行交互的。而在游戏过程中,依旧少不了GUI界面的出场,比如说状态显示界面(Head-up Display,HUD),HUD,这个界面提供一切和游戏有关的信息。用于提供玩家剩余任务时间,生命值,坐标位置,以及更多信息。

 


让我们欣赏一部分近期的3A游戏大作的UI界面美图吧:

 

《鬼泣5》:

 

 

 

《英雄无敌6》:

 

 

 

 欣赏完了,我们继续开讲吧。

 

 





 

二、关于状态显示界面(HUD)



这一节里让我们一起科普HUD的概念。

我们知道,通常情况下在游戏中屏幕上会有很多的小的界面模块配上文字,为玩家提供了一些有用的信息,比如玩家剩余任务时间,生命值,魔法值,坐标位置等等更多的信息。而因为在玩家和游戏交互的过程中,这些界面是透过摄像机视角显示出来的,它们被称为HUD(heads-up-display)。在视频游戏中,HUD就是一类可以实时向玩家显示有用信息和符号的GUI,并且它和诸如游戏菜单这样的其他界面不同.HUD中通常没有按钮、编辑框或者适合玩家交互的内容,因为玩家往往都是被游戏本身的画面和内容所吸引,而不是去关注HUD。所以呢,HUD通常并不去使用可以交互的元素,而倾向于使用文本和图像来表示某些信息。所以,游戏选项和偏好设置这样的内容不是HUD的菜,它们直接交由系统菜单来完成。

下面我们看一看更加规范化的HUD的介绍。

HUD,heads-up-display,硬着过来翻译就是“抬头显视设备”- -。这是一个从军事领域起源的技术,可以把一些重要的战术信息显示在正常观察方向的视野范围内,而同时又不会影响对于环境的注意,也不用总是转移视线去专门观察仪表板上的那些指针和数据。游戏借鉴了这个概念,把游戏相关的信息以类似HUD的方式显示在游戏画面上,让玩家可以随时了解那些最重要最直接相关的内容。当然玩家要获得游戏信息可以有别的方式,比如菜单。菜单有着专门的界面,可以容纳更大的信息量,但却不能和游戏画面同时出现。调出菜单意味着中断游戏流程,HUD则在提供必要的信息的同时完全避免了这个问题。

虽然菜单提供了大量的信息,然而对于处在自由行动状态下的玩家而言,这些信息都不是立刻需要获取的。HUD只提供了最重要最基本的内容:当前场景的地图。切换到战斗状态下之后,HUD所提供的信息便会转变为那些只和战斗相关的部分。

记得最早的游戏pong在设计的时候就没有HUD的。对于这样一个简单的游戏而言,唯一对玩家有意义需要及时掌握的就是双方的比分,而最早版本的pong没有这个功能,玩家需要自己去记录比分。游戏设计者很快意识到了这个问题,HUD很快就被整合到了后来的游戏之中,并随着游戏的进化一起演变,完善。

 

如果被上面的这些书面语绕晕了没关系,说了这么多,一言以蔽之:菜单的目的是大而全,HUD的目的则是少而精。HUD主要注重的是实时向玩家显示有用信息和符号的GUI,和而系统菜单GUI可以给玩家提供更多更全的信息。

不同类型的游戏玩起来的重点不一样,HUD在提供的信息方面也有很大的差别。我们不妨按照游戏的类别,来看看各种游戏的HUD设计的模式和重点。


1.角色扮演类游戏

取决于游戏是否会在行动场景和战斗场景之间切换,角色扮演游戏的HUD设计会有所不同,关于行动的那一部分内容,比如地图和方向指示之类的信息可能会被单独分列出来。但总体上角色扮演游戏的HUD信息量基本是一致的:玩家的生命,魔法,行动力,状态(或者其它因游戏而异的内容)等等的数值,玩家可以“一键”接触到的物品魔法等等东西,如果物品和魔法的内容很复杂,那么一般都会把全面调节的功能交给菜单来完成。比如预设快捷键和菜单光标位置记忆功能就是这样的目的,把菜单中全面而细微的调节能力中,挑选出一些最重要的,放到HUD上来,共玩家选择使用。


2.格斗游戏

无论格斗游戏系统本身怎么进化,从2D变到3D,格斗游戏的HUD总是保持着自己一贯的特色。格斗游戏的HUD大多分成两个部分:第一,对战斗数据的统计,第二,对战斗中精彩场面的描述。前者就是那些显眼的血槽,还包括时间,局数计分。后者则是对于连击之类的精彩动作的积分等等信息。其中血槽这个东西是游戏HUD设计上一个非常典型的东西。


3.体育游戏

体育类游戏在设计HUD的问题上有着天然的两个参考坐标系:电视转播画面和球队的战术分析图。游戏的HUD结合了这两者,即体现出了电视转播画面的现场感,也做出了战术分析图那样的清晰感,让玩家尽可能的在有身临其境的感觉的同时也对比赛局面有着清晰的了解。实际上体育类游戏的HUD设计作的是如此的好,以至于最近以来,很多体育项目的电视转播画面开始学习这类游戏的HUD设计,往画面上添加一些即时的比赛信息和战术分析。


4.驾驶模拟类游戏

这类游戏所要模仿的对象就是HUD这个概念的来源的地方,所以驾驶模拟类游戏HUD设计的原则也就变得非常简单而直接:尽可能的去重现模拟对象的原始HUD就可以了。当然根据游戏模拟真实的程度不同,再现真实HUD设计的程度也有所区别。HUD的设计始终存在一个如何抽取最重要的信息提示玩家的问题,过于仿真的游戏HUD设计将大量的信息不加选择的堆在玩家面前。对于游戏本身“模拟”这个概念而言,是好事,但对于像通过这些游戏来体验现实生活中不可能接触到的东西这个目的而言,高度的仿真模拟往往会成为上手的障碍。游戏毕竟是游戏,游戏的HUD如何在仿真模拟和抽象表现上把握平衡,是这类游戏的一个突出问题。


5.动作射击类游戏

射击类游戏的HUD通常都包括了玩家的状态,玩家的武器状态,地图,以及目标指示这四个方面。第三人称的射击游戏或者团队策略类射击游戏在HUD设计上和传统的第一人称射击游戏区别也不是很大,重点同样在这些要素上。HUD的引入给所有的射击类游戏,无论游戏本身的背景设定是在什么样的时代,都带来了一定的科幻未来的要素。真实的战斗中,对于战场情况的把握从来都是很大的挑战,不断进步的单兵信息化装备正是力求解决这些问题。射击类游戏通过HUD的引入超前的解决了这个问题。就目前而言,感觉做的最好的射击类游戏HUD恰恰就是一些未来题材的射击游戏,等下在HUD进化中我们会看到例子。


6.策略类游戏

最为复杂的一类游戏HUD,事实上在这类游戏里面HUD和菜单往往难以截然区分。因为玩家几乎每时每刻都需要确实的掌握整个游戏空间里大量单位的行动。HUD是简化了的菜单,但在很多的策略类游戏上,简化只是一个美好的愿望,游戏本身的复杂程度和玩家的“上帝”视角导致了这类游戏必然随时都有大量的信息反馈和大量的命令等待输入。策略类游戏的HUD如此的复杂,以至于在控制器键位相对较少的游戏主机上,这类游戏的流行程度始终达不到PC上同类游戏的流行度。游戏本身机制导致的复杂HUD设计应该是这类游戏受众群体局限性产生的原因之一。

其它类型的游戏,比如平台游戏,益智游戏等等在HUD设计上感觉并没有什么特别的地方。它们的HUD只要能清晰的交代出游戏人物(如果有的话)的状态和游戏的进展程度(得分之类的信息)就可以了。

 

如果看到这里觉得累了,依旧是欣赏一部分近期的3A游戏大作的UI界面美图吧:


《孤岛危机3》:



《仙剑奇侠传五 前传》:

 

 

《刺客信条4黑旗》:


 

 

 




三、开始GUI系统的设计

 

在这篇文章里面,我们将一起去实现一个简单而健全的GUI系统。这个系统既有HUD的功能,也可以创建GUI菜单。依旧是和之前的其他系统一样,封装在一个类中,这次的类是D3DGUIClass。

 

下面又到了天马行空的设计时刻了——在实现GUI系统之前,让我们设计出心目中的GUI系统该有的功能。

 

1.大体说明

首先需要说明的是,我们这次设计的GUI系统主要用于演示之用,扩展性很强,需要的更多功能完全可以在这个GUI的系统上进行二次开发,来增强它的特性和功能。

GUI系统主要由按钮和静态文本控件对象组成,当然,还少不了背景图的显示。由于GUI系统是2D的,这意味着指定对象位置时,是用不到Z轴的。另外,我们决定使用正交投影的方式来渲染GUI,这样可以根据像素的位置来指定屏幕的位置。

让我们来回忆一下,(0,0)对应的是屏幕的左上角。在windows系统中,左上角就是(0,0)。有了这个信息,就可以轻松地确定玩家的鼠标指针是否悬停在GUI系统的控件之上,或者说正在点击这个控件。


2.关于布局规划和背景图

在设计和规划按钮和文本位置时,我们只要牢记窗口左上角的坐标是(0,0),就能随心所欲的创建各式各样的限制的系统范围内的心仪的GUI布局出来。对于背景图的话,其实没必要考虑它的位置,因为这个图像就是一个由两个三角形构成的全屏图像。只要系统知道当前程序的宽度和高度,就可以显示一个全屏纹理图。

 

3.关于按钮控件的实现

必不可少的特性就是可以点击的按钮控件,其实按钮控件的实现比点击图像更容易实现。由于按钮控件的位置是以像素来指定的,因此为了确定鼠标指针是否在按钮上或者按下了按钮,其实就是检查当前鼠标指针的位置是否落在按钮区域内。因为Windows操作系统用像素指定鼠标位置且屏幕的左上角为(0,0),所以检查鼠标的坐标是否处于按钮四个角的坐标范围内就可以了,即检查如下四个方面:

按钮的左侧坐标位置是否小于鼠标指针的X坐标,按钮右侧坐标位置是否大于鼠标指针的X坐标,按钮的上侧坐标是否小于鼠标指针的Y坐标,下侧坐标是否大于鼠标的Y坐标。如果四个都为真的话,那么就可以认定鼠标指针就在按钮控件之上了,然后便通过消息过程来检测是否按下的鼠标左键这个状态,如果按下了鼠标左键,那么就可以确定玩家不仅仅是把鼠标放在了按钮之上,而是同时点击了按钮。我们还在这个GUI系统中实现了通过鼠标的悬停和点击动作,来改变按钮的外观,在按下按钮后有一定的动画效果。

根据上面的描述,我们可以写出的实现代码如下:

 

其中pControl是一个自定义的GUICONTROL结构体的指针对象

 

                            //检查鼠标是否悬停或者点击了按钮                            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;                            }

 


4.类的框架设计

因为这个GUI系统的实现还有一定的细节需要详细说明,所以决定分两次更新来讲解。这次我们先把功能完整的类的实现结果给大家,并告诉大家如何使用,说明一下main函数相对于之前有哪些细节需要改变,然后GUI系统类的实现细节留待下篇讲解(如果需要额外用一次更新来讲解的话)。

还是把详细注释的头文件贴一下吧:

//====================================================// Name: D3DGUIClass.h//      Des:一个游戏GUI界面系统类的头文件// 2013年 11月17日  Create by 浅墨//==================================================== #pragma once  // 所支持的控件类型宏#define UGP_GUI_STATICTEXT                 1#define UGP_GUI_BUTTON                     2#define UGP_GUI_Background                 3 // 鼠标按键状态宏#define UGP_BUTTON_UP                      1#define UGP_BUTTON_OVER              2#define UGP_BUTTON_DOWN                    3 // 设置一些GUI中用到的控件ID#define STATIC_ID_1  1#define STATIC_ID_2  2#define BUTTON_ID_1  3#define BUTTON_ID_2  4#define BUTTON_ID_3  5#define BUTTON_ID_4  6   // FVF灵活顶点类型的结构体struct GUIVERTEX{
              floatx, y, z, rhw;         unsignedlong color;         floattu, tv;};#define D3DFVF_GUI (D3DFVF_XYZRHW |D3DFVF_DIFFUSE | D3DFVF_TEX1)  //控件属性结构体struct GUICONTROL{
              //操作类型,ID和颜色         intm_type;  //控件类型         intm_id;  //控件ID         unsignedlong m_color; //控件颜色         intm_listID;   //如果是文字的话,这个变量就表示它使用的字体,否则就表示顶点缓存         floatm_xPos, m_yPos;   //控件的起始位置         floatm_width, m_height;   // 控件的宽度和高度         wchar_t*m_text;   // 文字内容         LPDIRECT3DTEXTURE9m_Background;   // 控件背景的填充图像         LPDIRECT3DTEXTURE9m_upTex, m_downTex, m_overTex;   // 存放按钮弹起,按下和鼠标经过时的3张纹理图};   class D3DGUIClass{
      private:         LPDIRECT3DDEVICE9m_pd3dDevice;  //D3D设备对象             LPD3DXFONT*m_pFonts;  //D3D字体对象         GUICONTROL*m_pControls;  //控件对象         LPDIRECT3DVERTEXBUFFER9*m_pVertexBuffer;   //顶点缓存对象指针         GUICONTROLm_Background;  //背景图对象         LPDIRECT3DVERTEXBUFFER9m_BackgroundBuffer;   //背景图缓冲区对象          boolm_bIsBackgroundUsed;  //一个标识,用于标识是否已经用了背景         intm_nTotalFontNum;              //字体数目计数器         intm_nTotalControlNum;        //控件数目计数器         intm_nTotalBufferNum; //缓冲区数目计数器          intm_nWindowWidth;    //窗口宽度         intm_nWindowHeight;   //窗口高度   public:         D3DGUIClass(LPDIRECT3DDEVICE9device, int w, int h);         
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值