游戏进阶之千里之行始于足下(一)_第1页
游戏进阶之千里之行始于足下(一)_第2页
游戏进阶之千里之行始于足下(一)_第3页
游戏进阶之千里之行始于足下(一)_第4页
游戏进阶之千里之行始于足下(一)_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第第页游戏进阶之千里之行始于足下(一)游戏进阶之千里之行始于足下(一)-

发表于:2023-04-28来源::点击数:标签:千里之行始于足下GDI进阶游戏

GDI汇编:Windows是一个基于图形的操作系统,它的图形功能是通过一个称为GDI图形子系统来实现的。通过使用GDI,你可以向系统中的任何设备上画图比如:显示器、系统内存、打印机等等,因为GDI为我们作了很多幕后工作。不幸的是,GDI在有些时候不能满足你

GDI汇编:

Windows是一个基于图形的操作系统,它的图形功能是通过一个称为GDI图形子系统来实现的。通过使用GDI,你可以向系统中的任何设备上画图比如:显示器、系统内存、打印机等等,因为GDI为我们作了很多幕后工作。

不幸的是,GDI在有些时候不能满足你性能上的要求,特别是游戏,对于图形功能要求是很高的,同时对于速度的要求也是很苛刻的,这就是DrectX出现的原因。我们首先来学习一下GDI,因为即使你要用DirectX,一些GDI知识也是必备的。

矩形和点:

在我们介绍GDI对象之前,我们先来看看两个非常有用的结构点和矩形以及作用于他们上的功能函数。矩形在DirectX中也是经常用的,在以后的学习过程中你将会发现这一点。

我们首先来看这两种结构的定义:

typedefstructtagPOINT{

LONGx;

LONGy;

}POINT,*PPOINT;

typedefstruct_RECT{

LONGleft;

LONGtop;

LONGright;

LONGbottom;

}RECT,*PRECT;

矩形是由四个点来描述的:(左,上),(右,上),(左,下),(右,下)。在这里需要注意的是矩形的右和下两条边时不属于矩形的。

用于操作矩形和点的函数:

我把这些函数分为三类:第一类是用于创建或者赋值的,第二类是用于操作的,第三类是用于测试的。

函数名称类型作用

SetRect创建赋值用于设置RECT的成员变量

SetRectEmpty同上用于将RECT的所有成员置0的

CopyRect同上用于将一个矩形的成员值赋给另外一个矩形的

IntersectRect操作用于找到两个矩形的交集

UnionRect同上用于创建同时包含两个矩形的最小矩形

OffsetRect同上用于移动一个矩形

EqualRect(测试)(测试)两个矩形的成员是否相等

IsRectEmpty同上测试一个矩形的成员是否都为0

PtInRect同上测试一个点是否位于一个矩形之内

关于这些函数的具体定义请大家参阅MSDN.

窗口点滴:

我们都很清楚,一个窗口所包含的不只是我们能够绘画的区域.根据用处的不同,一个窗口包含最大化,最小化按钮,标题栏,一个关闭按钮,一个系统菜单.滚动条等等.所包含的元素取决于你所创建的窗口样式.不过这些都不用我们担心,系统会为我们很好的绘制他们,我们所要关心的就是在客户区如何把自己的东西绘制好.

正如上面所提到的,我们可以自由绘制的区域是"客户区".除客户区以外的任何区域都属于非客户区.任何时候我们想重新绘制客户区的话都可以通过发送WM_PAINT消息来实现.

GetClientRect()

这个函数用于得到客户区的大小,并把它保存到一个矩形里面.

GetWindowRect()

这个函数用于得到整个窗口的大小,并把结果村到一个矩形里面.

以上两个函数的具体定义请参阅MSDN.

AdjustWindowRect()AdjustWindowRectEx()

这两个函数用于让客户区适应窗口的大小,使用哪个取决于你创建窗口时使用的是:CreateWindow()还是CreateWindowEx()

设备环境:

(Windows)可以向多种设备上绘制图形,比如显示器,打印机等.这是通过使用设备环境来实现的.设备环境是对具体设备的抽象.设备环境为我们屏蔽了诸多硬件的不同,让我们以同一种方式向所有的设备上绘制图形.项具体设备上转化的工作就交给了设备环境.这就是所谓的设备无关性.

当然,设备无关性是有代价的.使用设备环境要比直接跟硬件交互慢得多,因为绘制命令要经过好几层才能到达所要求的硬件.这个问题解决的方案就是DirectX,它提供了一种更为底层的操作硬件的方式(DirectX直接跟设备驱动程序交互).

下面是有关设备环境的函数:

GetDC()这个函数为特定的窗口向系统"借"设备环境,大家记清楚了,是借,要还的!

ReleaseDC()这个函数是将设备环境还给系统.

以上函数的具体定义请参阅MSDN.

难道所有的设备环境都必须跟窗口相关吗?答案是否定的,内存设备环境将是这个问题的最好的例子:

内存设备环境:本质上就是一块内存,但你可以象是对待设备一样对待这块内存.大家可能会问这有什么用处呢?这当然有用处,大多数游戏都是使用双缓冲以消除闪烁,为显示器创建一块内存设备环境就能消除闪烁.在以后的学习中我们会逐步介绍.

相关函数:

CreateCompatibleDC()创建内存环境,实质上就是申请一块内存

DeleteDC()释放内存

对于这块刚刚申请的内存环境里面有什么呢?如果你非要问个究竟的话那我只能告诉你:里面只有一个1*1的单色位图.1*1单色位图有什么用处呢?答案是为了内存设备环境的存在,因为空的设备环境是没有办法存活的.

GDI对象

一提到对象大家马上就想到了OO,但是这些GDI对象跟现在的面向对象里面的对象是有区别的,当然也有相同的地方。我

们是通过句柄来操作对象的。

有五种GDI对象是需要我们学习的,他们分别是:HBITMAP,HBRUSH,HPEN,HFONT,HRGN,以下就是对他们的详细介绍:

.HBITMAP位图对象它是由一个二维的图像组成的,在Windows中,它通常是利用一个位图创建的。

.HBURSH画刷对象可以把它认为是一种沾满油漆的刷子,那么它的作用也就很显而易见了,就是把设备环境的某个特定区域刷成特定的颜色。

.HPEN画笔对象是具有一定颜色跟风格的画笔,它主要是用来绘制图元(线,矩形,椭圆等)

.HFONT字体对象可以认为它是具有各种风格的字符集,用来向设备环境上绘制文本。

.HRGN区域对象是可以被修剪,填充的一个具有某种形状的区域,可以使矩形,椭圆,多边形,或者你能想到的任何形状。

在一个特定时刻里一个设备环境里各种GDI对象只能存在一个实例,也就是说,在一个时刻里,一个设备环境里面只能有一个位图,一枝画笔,一个画刷,一种字体,一种特定区域形状。可以把它的工作用以下场景来描述:一个用于绘制图形的设备(设备环境),它首先需要一张纸(位图对象)来绘制图形,一枝笔(画笔对象)来画,一个刷子(画刷对象)来填充背景,一种字体(字体对象)来写字,以及一种风格(区域对象)来画图.

CreatePen()用于创建画笔对象

CreateSolidBrush()用于创建画刷对象

CreateBitmap()用于创建位图对象

CreateFont用于创建字体对象

DeleteObject()销毁所创建的对象

SelectObject()用于将指定的对象选入设备环境

切记:

从技术角度上来看,Windows为每个应用程序维护一个特定的内存区域,当这个应用程序结束时Windows会自动释放该应用程序所占有的内存区域,我们似乎不用把创建的对象删除掉,但是当这个程序要运行很长时间,并且不断向系统申请内存的时候我们就该傻眼了,因为我们的程序就会狂吃内存,这是我们所不愿见看到的,所以,作为一个良好的(编程)习惯,一定把自己所申请的内存给释放掉.

关于像素:

我们的显示器是由一个个点组成的,其中的一个点就是一个像素.这是我们所能操作的最小单元,当然点越多越小时我们就感觉越清晰.在我工作的大部分时间里我的显示器的分辨率都是1028*768,这意味着我在我的显示器上有超过750,000个点。除了显示器的宽和高你有一个颜色深度是你必须关心的,即一个像素的颜色是用几个比特来表示的,如果是一个比特,很显然只能够表示两种颜色,也就是单色显示器。最常用的是8,16,24和32比特颜色深度。8位色又称为时索引色,它涉及到调色板的相关知识,这里我就不详细介绍了,相关的介绍已经很多了。

对于16,24,32位色,它们都是通过RGB三原色来表示一个像素的颜色的红,绿,蓝。

每个像素的表示方式在DirectX里特别关心的,在GDI里,我们可以把一切都看成是24比特的,系统会为我们作相应的转换工作的。

在GDI里,每种颜色都是由COLORREF来表示的。COLORREF在本质上就是一个整数。共24比特,每种颜色用8比特来表示。

下面是RGB宏定义:

#defineRGB(r,g,b)

((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))8))|(((DWORD)(BYTE)(b))16)))

有关像素的操作:

SetPixel()将特定像素变成特定颜色

SetPixelV()功能同上,但返回值不同

GetPixel()返回指定像素的颜色值

以上函数详见MSDN

将这段代码防盗消息处理函数里面:

caseWM_MOUSEMOVE

{

if(wParamMK_LBUTTON)

{

intx=LOWORD(lParam);

inty=HIWORD(lParam);

HDChdc=GetDC(hWindow);

SetPixelV(hdc,x,y,RGB(255,255,255));

ReleaseDC(hWindow,hdc);

}

return0;

}

break;

你将看到什么呢?哈哈,这就是我们画图软件的雏形,鼠标所到之处都会留下痕迹,这也是让我们感到兴奋的地方.当然这里面有太多的不足,可别忘记了,这才刚刚开始啊!!

使用画笔:

在前面我们完成了一个画图软件的雏形,我们看到了能够操作像素给我们带来的快乐,但是如果我们只能够操作像素的话那就很不爽了,试想在一个场景多变的游戏里面,如果我们来一个像素一个像素的来处理的话那么游戏编程绝对是件痛苦的事情。好在我们有画笔,画刷,以及后面将要讲到的高级工具。

前面我们已经提到过关于画笔的创建工作,在这里我们再稍微提及一下:

CreatePen()用于画笔的创建,它的参数决定了它的风格

详见MSDN

图形绘制函数:

在介绍图形绘制函数之前,我们先来讨论一下设备环境中的当前位置。设备环境本身维护着一个当前位置,在绘制的过程中它记录着你所走过的轨迹(点)。你可以通过以下函数来修改这个当前位置(CP):

MoveToEx()用于设定当前位置CP

GetCurrentPosition()用于获得当前位置CP

详见MSDN

现在我们已经可以改变和得到当前位置CP,但仅仅能做这些事是远远不够的。

LineTo()用于画一条从CP开始到指定位置的直线

我们来看下面的代码片断:

caseWM_LBUTTONDOWN

{

intx=LOWORD(lParam);

inty=HIWORD(lParam);

HDChdc=GetDC(hWindow);

MoveToEx(hdc,x,y,NULL);//修改当前位置CP

ReleaseDC(hWindow,hdc);

return0;

}

break;

在上面这段代码里面我们是根据鼠标左击的位置来设定设备的当前位置CP,接着看这段代码:

caseWM_MOUSEMOVE

{

if(wParamMK_LBUTTON)

{

intx=LOWORD(lParam);

inty=HIWORD(lParam);

HDChdc=GetDC(hWindow);

LineTo(hdc,x,y)

ReleaseDC(hWindow,hdc);

}

return0;

}

break;

在我们按下鼠标左键的时候,我们用鼠标的当前位置设置了CP,当鼠标移动的时候我们时刻记录着光标的当前位置并CP向这个位置画一条直线。

使用画刷:

在GDI里,我们用画笔对象来绘制我们想要得的图形,如果我们要想填充的话就要依靠画刷了,有很多创建画刷的函数,在这里我给大家介绍两个最常用的,其它的大家可以参阅MSDN作更为详细的了解:

CreateSolidBrush()用于创建纯色的画刷

CreateHatchBrus

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论