您现在的位置是:首页 > 编程 > 

游戏编程之十六 扩展(DDEX2和DDEX)

2025-07-28 05:41:22
游戏编程之十六 扩展(DDEX2和DDEX) DirectDraw 游戏编程基础() 游戏使计算机的发展超越了晶体管时代例一的扩展(DDEX2和DDEX)DDEX1包含了一个最基本的DirectDraw的实现方法。它生成了DirectDraw和DirectDrawSurface对象,同时也生成了一个主表面(Surface)和与之相关的后台缓冲区,并在后台缓冲区打印文本,并可以在表面(Su

游戏编程之十六 扩展(DDEX2和DDEX)

DirectDraw 游戏编程基础()

游戏使计算机的发展超越了晶体管时代

例一的扩展(DDEX2和DDEX)

DDEX1包含了一个最基本的DirectDraw的实现方法。它生成了DirectDraw和DirectDrawSurface对象,同时也生成了一个主表面(Surface)和与之相关的后台缓冲区,并在后台缓冲区打印文本,并可以在表面(Surface)之间进行切换。

在DirectX SDK(DDEX2)中的第二个DirectDraw 例程扩展了关于DDEX1应用程序。DDEX2包括将一个位图文件载入到后台缓冲区的函数。

第三个DirectDraw 例程将这一函数进一步地扩展了。除了主表面(Surface)和后台缓冲区之外,DDEX还生成了两个隐屏表面(Surface),并且在每一个隐屏表面(Surface)之中都载入了一个位图文件。然后,DDEX使用IDirectDrawSurface::BltFast方法,将一个隐屏的内容复制到后台缓冲区中。之后,弹出这些缓冲区,并且将下一个隐屏表面(Surface)的内容复制到后台缓冲区。

以下的部分将更详细地检查这一新的函数。

在一个表面(Surface)上载入一个位图(Bitmap)

就与DDEX1一样,dolnit是DDEX2应用程序的初始化函数。虽然,在DDEX2中,DirectDraw的初始化方式表面上与在 DDEX1中的DirectDraw的初始化方式不太一样,但它们的实质是一样的。这一过程如下列的程序代码所示:

LPddPal = DDLoadPalette(LpDD, szBackground);

if (LpddPal == ULL)

goto error;

ddrval = LpDDSprimary->SetPalette(LpDDPal);

if( ddral != DD_OK )

goto error;

// Load a bitmap into the back buffer。

Ddrval = DDReLoadBitmap(LpDDSBack, szBackground);

if( ddrval != DD_OK )

goto error;

生成调板

这个程序代码的第一行是:从DDLoadPalette函数返回一个值。如果你想知道在哪能到DDLoadPalette,你可以在\DXSDK|SAMPLES|MISC目录中的文件中到它。你会发现,在DirectX SDk的大部分DirectDraw例程中都使用了文件。最为关键的是:该文件上包括了能从文件中或是从资源中载入位图和调板的函数。这些函数的代码并非一遍遍地重复出现在例程文件中,而且被放置在能被重复使用的同一文件之中。

注意:如果你正在使用MS Developer Studio(微软开发工作室)编辑DDEX2和用DirectX SDK提供的其它工具,你必须把文件插入到DDEXx文件工作区的文件表中。重申一遍:在工作区中必须包括:

1. 在插入(insert)菜单上,单击Files进入Projeects。

2. 单击Browse.

. 单击DXSDK\SDK\SAMPLES\MISC\目录。

4. 单击

5. 单击ADD

对于DDEX2来说,从Back.bmp文件中,DDLoadPalette创建了一个DirectDraew对象。DDLoadPalette函数实际上是来检查用以产生调板的一个文件或资源是否存在。如果不存在的话,该函数就创建一个缺省的调板,对于DDEX2 来说,DDLoadPalette函数从文件中提取调板信息,并通过ape指针将其存储在一个指定的结构中,然后它生成DirectDrawPalette 对象。如下面的代码所示:

pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, ULL);

return ddpal;

当IDirectDraw::Createpalette方法返回后,ddpal参数将指向DirectDrawPalette对象,其中,对象DirectDrawPalette是从DDLoadPalettede的调用返回的。

Ape参数是一个指针,它可以包括2,4,16或256个入口,呈直线分布。这些入口的数目由IDirctDraw::CreatePalette参数决定。在这种情况下,dwFLags参数被设置为DDPCAPS_8BIt,它表示:在这个结构中有256个入口。每个入口包括4位(一位红通道,一位绿通道,一位兰通道和一个标志位)。

设置调板

在生成调板之后,你要通过调用IDirectDrawSurface::SetPalette方法,将DirectDrawPalette对象的指针转到主表面(Surface)上,如下列代码所示:

ddrval = LpDDSPrimary->SetPalette(LpDDPal);

if( ddrval != DD_Ok )

// SetPalette failed

一旦你已经调用了IdirectDrawSurface::SetPalette,DirectDrawPalette对象就被嵌入到DirectDrawSurface对象中了。不论何时你需要改变这一调板,你要作的就是生成一个新的调板并重新设置该调板。(这就如例程中所做的一样。然而,也有其它的改变调板的方式。我们可以在其它例程中看到)。

在后台缓冲区中载入一个位图文件

一旦DirectDrawPalette对象被嵌入到DirectDrawSurface对象之中,DDEX2就将Back.bmp bitmap载入到后台缓冲区中。使用下例的程序代码可实现该过程:

// Load a bitmap into the back buffer.

Ddrval = DDReLoadBitmap(LpDDSBack, szBackground);

if( ddrval != DD_Ok )

// Load failed

DDReLoadBitmap是出现在中的另一个函数。它从一个文件或资源中将一个位图文件载入到一个已经存在的DirectDraw表面(Surface)之中。(就象在DDEX5中那样,你可以使用DDLoadBitmap创造一个表面(Surface)并且将位图载入那个表面(Surface))。对于DDEX2来说,DDReLoadBitmap把szBackground指向的Back.bmp载入到ipDDSBack指向的后台缓冲区,DDReLoadBitmap调用DDCopyBitmap函数,将文件复制到后台缓冲区中,并且将缓冲区扩展到适当的。

DDCopyBitmap函数将位图复制到内存之中,然而利用GetObject函数得到位图的大小。DDCopyBitmap然后使用下列的代码得到后台缓冲区的大小(它可以放置位图):

//

// get size of surface

//

ddsd.dwSize = sizeof(ddsd);

ddsd.dwFlags = DDSD_HEIGHT DDSD_WIDTH;

pdds->GetSurfaceDesc(&ddsd);

ddsd是指向DDSRFACEDESC结构的一个指针。该结构存储了DirectDraw表面(Surface)的当前描述。在这种情况下,我们需要注意的是:DDSURFACEDESC的成员描述这个表面(Surface)的高度和宽度,分别表示为:DDSD_HEIGHT和 DDSD_WIDTH。调用IDirectDrawSurface::GetSurfaceDesc方法,把适当的值来载入到这个结构。对于DDEX2来说,这些值将是:高480和宽640。

DDCopyBitmap函数锁定表面(Surface)并将位图文件复制到后台缓冲区,使用StretchBit函数延伸或压缩后台缓冲区到可适用的大小。表示如下:

if ((hr = pdds->GetDC(&hdc)) == DD_OK)

{

StretchBlt(hdc, 0,0,ddsd.dwWidth, ddsd.dwHeight, hdcImage,x, y, dx, dy, SRCCOPY);

pdds->ReleaseDC(hdc);

}

弹出表面(Surface)

在DDEX2例程中的弹出表面(Surface)操作本质上与在DDEX1例程中的弹出操作是同样的过程。但是在表面(Surface)丢失的情况下,你必须通过调用DDReLoadBitmap函数,在表面(Surface)恢复之后,,将bitmap再次载入到后台缓冲区中。

从一个隐屏表面(Surface)按位隔行拷贝

DDEX2是在后台缓冲区中取出和放入位图的,然后在后台缓冲区和主缓冲区之间切换。这并不是一个展示位图的很实际的方法。DDEX扩展了DDEX2的功能,它包括了两个隐屏缓冲区,且在其内部存放有两个位图(一个对应于偶行屏幕,另一个对应于奇行屏幕)。DDEX把一个屏幕按位隔行拷贝到后台缓冲区中,再把另外一个屏幕按位隔行拷贝到另一个后台缓冲区中,然后弹出表面(Surface)。

生成隐屏表面(Surface)

下列的代码在DDEX 中加到dolnit 函数可生成两个隐屏 缓冲区:

// Create an offscreen bitmap.

Ddsd.dwFlags = DDSD_CAPS DDSD_HEIGHT DDSD_WIDTH;

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREEPLAI;

ddsd.dwHeight = 480;

ddsd.dwWidth = 640;

ddrval = lpDD->CreateSurface( &ddsd,&lpm DDSOne,ULL);

if (ddrval != DD_OK)

{

return initFail(hwnd);

}

//Create another offscreen bitmap.

Ddrval = lpDD->CreateSurface( &ddsd,&lpm DDSTwo,ULL);

if (ddrval != DD_OK)

{

return initFail(hwnd);

}

如代码中所示,dwFlags成员设定了应用程序将使用DDSAPS结构,并且设置缓冲区的高度和宽度。表面(Surface)是一个平面式隐屏缓冲区,就如同通过设置在DDSCAPS结构中的DDSCAPS_OFFSCREE标志所表示的一样。在DDSURFACEDESc结构中,高度和宽度被分别设置为480和640。通过使用IDirectDraw::CreateSurface方法,表面(Surface)就这样被生成了。

因为两个隐屏缓冲区有着同样的大小,故生成第二个缓冲区的唯一要求就是再运行IDirectDraw::CreateSurface(当然,要用不同的指针名字)。

通过在DDSCAPS结构中,或是设置DDSCAPS_SYSTEMMEMORY,或是设置DDSCAP_VIDEOMEMORY的容量,你可以将该:隐屏缓冲区或是放置在系统内存中或是显存中。通过将位图存盘在显存中,你可以增加隐屏表面(Surface)和缓冲区之间切换的速度。当我们开始讨论位图动画时,速度将变得更加重要。但是,此时你应当注意:如果你仅为隐屏缓冲区设置DDScAPS_VIDEOMEMORY,而没有足够的显存来保存整个位图文件,那么,当你试图创建表面(Surface)时,就会返回一个DDERR_OUTOFVIDEOMEMORY的错误值。

将位图文件载入后台缓冲区

在两个隐屏表面(Surface)生成后,DDEX#使用IITSURFACES函数,从Frnt.bmp文件中将位图文件载入到表面(Surface)中。InitSurfaces函数使用中的DDCopyBitmap载入这两个位图文件,如下列代码所示:

// Load our bitmap resource.

Hbm = (HBITMAP)LoadImage(GetModuleHandle(ULL),szBitmap,

IMAGE_BITMAP,0,0,LR_CREATEDIBSECTIO);

if (hbm == ULL)

return FALSE;

DDCopyBitmap(lpDDSone,hbm,0,0,640,480);

DDCopyBitmap(lpDDSTwo,hbm,480,640,480);

DeleteObject(hbm);

return TRUE;

如果你在MS Paint(微软画笔)或是另一个绘画程序中看到Frnt.bmp文件,你可以看到位图文件是由两个屏幕组成的(其中一个在另一个的上部)。DDCopyBitmap函数在屏幕相汇点上将位图文件一分为二,并将第一份位图文件载入第一个隐屏表面(Surface)(IPDDSOne)中,同时将第二份位图载入第二个隐屏表面(Surface)(IPDDSTwo)中。

将隐屏表面(Surface)按位隔行拷贝到后台缓冲区

WM TIMER包含了写表面(Surface)和弹出表面(Surface)的代码。在DDEX的情况下,它包含下列的代码,用来选择适当的隐屏表面(Surface),并将它按位隔行拷贝到后台缓冲区中。

rcRECT.LEFT =0;

RCRECT.TOP =0;

RCRECT.right =640;

rcRect.bottom =480;

if(phase)

{

pdds = lpDDSTwo;

phase = 0;

}

else

{

pdds = lpDDSOne;

phase = 1;

}

while(1)

{

ddrval =lpDDSBack->BltFast(0,0,pdds,&rcRect,FALSE);

if(ddrval == DD_OK)

{

break;

}

"phase"决定了将哪一个隐屏表面(Surface)按位隔行拷贝到后台缓冲区中。然后,IDirectDrawSurface::BltFAst方法被调用,并将已经被选择好的隐屏表面(Surface)按位隔行拷贝在后台缓冲区中,开始位置为(0,0),它位于屏幕的左上角。参数rcRect指向结构Rect,它定义了隐屏表面(Surface)的左上角和右下角。最后的参数被设置为FALSE(或0),这就表明了没有专门的转移标志以备使用。

在这里,我很想补充说明的是:在何种情况下应该选择IDirectDrawSurface::Blt方法,在何种情况下应该选择IDirectDrawSurface::BltFast方法。如果你正在从一个隐屏缓冲区中进行一次按位隔行拷贝,你应当使用IDirectDrawSurface::BltFast。如果你的系统显存中是使用硬件进行按位隔行拷贝,你虽然不会真正提高拷贝的速度,但是,它会节省系统模拟硬件时间,从而使整个按位隔行拷贝时间缩短约10%。因此,我推荐读者使用IDirectDrawSurface::BltFast进行所有的显示操作(从显存按位隔行拷贝到显存中)。如果你正在从系统内存中按位隔行拷贝,或者要求专门的硬件标志位,这样的话,你就必须使用IDirectDrawSurface::Blt。

一旦隐屏表面(Surface)被载入后台缓冲区中,后台缓冲区和主表面(Surface)就如同前边的例程中所显示的一样被弹出。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2022-04-06,如有侵权请联系 cloudcommunity@tencent 删除后台游戏编程对象函数

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1253034.html

相关标签:无
上传时间: 2025-07-27 22:27:48
留言与评论(共有 17 条评论)
本站网友 南昌不孕不育医院
16分钟前 发表
640
本站网友 专升本需要考哪几科
9分钟前 发表
如下列代码所示
本站网友 印花税下调
27分钟前 发表
本站网友 合肥白癜风
30分钟前 发表
Blt
本站网友 泌尿外科女医生
16分钟前 发表
同时将第二份位图载入第二个隐屏表面(Surface)(IPDDSTwo)中
本站网友 百日禁忌
1分钟前 发表
你可以在\DXSDK|SAMPLES|MISC目录中的文件中到它
本站网友 眼部去皱的方法
10分钟前 发表
本站网友 supervision
15分钟前 发表
虽然
本站网友 网络短信群发平台
18分钟前 发表
且在其内部存放有两个位图(一个对应于偶行屏幕
本站网友 天王山之战是什么意思
6分钟前 发表
Blt
本站网友 haosao
23分钟前 发表
DirectDrawPalette对象就被嵌入到DirectDrawSurface对象中了
本站网友 深度winpe
24分钟前 发表
然后它生成DirectDrawPalette 对象
本站网友 海陵教育
13分钟前 发表
或是设置DDSCAPS_SYSTEMMEMORY
本站网友 滴滴专车
24分钟前 发表
szBackground); if( ddrval != DD_Ok ) // Load failedDDReLoadBitmap是出现在中的另一个函数
本站网友 冥仙法门
13分钟前 发表
如果你正在使用MS Developer Studio(微软开发工作室)编辑DDEX2和用DirectX SDK提供的其它工具
本站网友 富力盛悦居
15分钟前 发表
ddpal参数将指向DirectDrawPalette对象