没有合适的资源?快使用搜索试试~ 我知道了~
DIRECTX中独占模式与窗口模式的切换
3星 · 超过75%的资源 需积分: 10 23 下载量 72 浏览量
2011-11-25
11:19:03
上传
评论
收藏 162KB DOC 举报
温馨提示
试读
19页
gamedev.net的文章,由高手翻译了,讲解DirectX中全屏与窗口的模式切换实现
资源推荐
资源详情
资源评论
DIRECTX 中独占模式与窗口模式的切换(一)
介绍
让你的游戏能够在独占(全屏)模式与窗口模式下运行应该很简单,但想要让它合理且优雅
的运行就要多做些工作了.在这篇文章中,我将用业界十分常用的 C++语言来讲解这方面的
技术,如果你想,可以用类把这个例子封装起来以便于使用.
我假设你已熟悉独占模式下的 DirectDraw 的设置与使用,这里我不再赘述,让我们开始
吧!
设计
DirectDraw 窗口模式下的初始化有好多与独占模式不同.最好的方法是在你程序的开
始就创建 DirectDraw 对象,第二步再创建所有表面,设置协调层级和显示模式, 初始化
你需要的变量,等等.独占模式与窗口模式的不同都体现在这第二步中,所以,你的函数可以
写成这样:
voidCreateDirectDraw();
voidDestroyDirectDraw();
和Š
voidCreateSurfaces(boolbExclusive,intnWidth,intnHeight,int
nBPP);
voidDestroySurfaces();
第 一 部 分 (CreateDirectDrawandDestroyDirectDraw) 分 别 创 建 和 销 毁
DirectDraw 对 象 . 你 自 己 应 该 可 以 完 成 的 . 第 二 部 分
(CreateSurfacesandDestroySurfaces)解决所有除去创建和销毁 DirectDraw
对象以外的事.看看 参数ŠbExclusive,它表明创建一个独占模式的表面或窗口模式的表
面 以 及 相 关 的 各 个 对 象 .参 数 Šwidth,height,bpp 用 以 描 述 显 示 模 式 ( 当
bExclusive 为 true 时)
我们需要稍微改变游戏循环以正确处理窗口模式.为了正常改变窗口模式我们增加了一个
函数:
voidSwitchMode(boolbExclusive,intnWidth,intnHeight,intnBP
P);
继续来看如何实现这此些函数!
CreateSurfaces
我们把这个函数分成两部分,分别实现独占模式和窗口模式下的 DirectDraw 的初始化,
如下:
if(bExclusive)
{
//exclusivecode
//savethemode
g_bExclusive=bExclusive;
}
else
{
//windowedcode
//savethemode
g_bExclusive=bExclusive;
}
你还需要创建一个全局变量 g_bExclusive 用以标志当前的模式,在游戏循环中要用到它
的.请明确 g_bExclusive 的重要性,我们借此追踪模式
你可以把你以前的代码放到 exclusive 部分,用参数 nWidth,nHeight,和ŠnBPP 设
置显示模式等.然后让我们一起来完成 windowed 部分的代码(我用了几个函数来实现,都
将它们分成了两部分,就像你在这个函数里看到的一样)
就和我前面提到的一样 ,当这个函数被调用时 ,DirectDraw 已经创建,所以初始化
DirectDraw 的下一步是通过 lpDD->SetCooperativeLevel()来设置协调层级.把
主窗口的句柄和 DDSCL_NORMAL 作为参数传给它:
lpDD->SetCooperativeLevel(hMainWnd,DDSCL_NORMAL);
如果你想使用多线程,把标识 DDSCL_MULTITHREADED 与 DDSCL_NORMA 相与传给它就是
了,但注意:在窗口模式下不能设置显示模式!所以下一步是创建主表面与后缓冲区.
在 窗口模式下你需要一个完全不同的”缓冲系统”,你不能在创建主表面时连接一个后缓冲
区然后调用 flip()函数来翻转,为什么?因为你在窗口模式下不能独 享显卡,而翻转是交
换主表面和一个与其相连的后缓冲区的地址的过程,显然,你不能在窗口模式下这么做,因
为此时你和其它应用程序共享主表面.
要使用窗口模式,应该用下面这个 DDSURFACEDESC2 结构去创建主表面:
DDSURFACEDESC2ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS;
ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
这些语句创建的主表面将使用现在的屏幕格式,而且你不能修改(因为是窗口模式),也请注
意我没有使用 DDSD_BACKBUFFERCOUNT 这个标识,这只能在独占模式下使用
然后再创建后缓冲区,代码如下:
DDSURFACEDESC2ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth=640;//whateveryouwant
ddsd.dwHeight=480;//whateveryouwant
注意这里也没有使用 DDSCAPS_BACKBUFFER 标识,因为这也是特别为独占模式应用程序
准备的
请记住,在 DirectDraw 中主表面往往表示整个屏幕.为了防止你在窗口模式下在整个屏
幕里作图,你可以给主表面连接一个裁剪器,并将其与主窗口相连(这很简单!)
LPDIRECTDRAWCLIPPERlpddClipper;
lpDD->CreateClipper(...lpddClipper...);
lpddClipper->SetHWnd(...hMainWnd...);
lpddsPrimary->SetClipper(...lpddClipper...);
简便起见,我省略了这些函数的其它参数
好了,这就是 CreateSurfaces 函数,接下来我们要看看如何清除对象了!
DestroySurfaces
你结束程序所用的清理代码也将有所不同.原来你只需要释放 DirectDraw 对象和主表面,
现在你还需释放后缓冲区和裁剪器.同样,用 if语句将处理独占模式的代码与处理窗口模
式的代码分开:
if(bExclusive)
{
//exclusivecode
}
else
{
//windowedcode
}
把你的独占模式的代码放入 exclusivecode 部分,然后我们来添加窗口处理代码.
把下面的代码加入到 windowedcode 部分:
if(lpddBack)
{
//releasethebackbuffer
lpddBack->Release();
lpddBack=NULL;
}
if(lpddPrimary)
{
//releasetheclipper(indirectly)
lpddPrimary->SetClipper(NULL);
lpddClipper=NULL;
//releasetheprimarysurface
lpddPrimary->Release();
lpddPrimary=NULL;
}
当你加入了上述代码后,让我们一起进入游戏循环!
由于论坛容量有限,分两部分贴出
当你加入了上述代码后,让我们一起进入游戏循环!
游戏循环
你也许认为在游戏循环中唯一真正的不同是当你在窗口模式下时把后缓冲区的内容贴到主
表面上而不是用翻转(fliping).好,我们就从那里开始.将你的渲染函数也用 if语句分
成两部分:
if(g_bExclusive)
{
//exclusivecode
}
else
{
//windowedcode
}
g_bExclusive 表示什么?这是我们用来追踪当前模式的全局变量!
把你原来独占模式下的渲染代码移植到 exclusivecode 部分,然后在 windowedcode
部分增加一个 Blt 函数,主表面作为目的表面,后缓冲区作为源表面,如下:
lpddPrimary->Blt(NULL,lpddBack,NULL,DDBLT_WAIT,NULL);
简 直和随手拿来一样简单!等等,这语句对整个主表面作图,不只是窗口!我们怎样才能用
DirectDraw 把整个后缓冲区复制到窗口的窗户区呢?好,这样, 我们先得到窗口的客户
区,然后把客户区矩形的两个点坐标转换成相对于屏幕左上角的坐标(屏幕坐标),再把这个
矩形作为 Blt 的第一个参数,这里是部分代 码:
//calculatetheclientrectinscreencoordinates
RECTrect;
ZeroMemory(&rect,sizeof(rect));
//gettheclientarea
GetClientRect(hMainWnd,&rect);
//copytherect'sdataintotwopoints
POINTp1;
POINTp2;
p1.x=rect.left;
p1.y=rect.top;
p2.x=rect.right;
p2.y=rect.bottom;
//convertittoscreencoordinates(likeDirectDrawuses)
ClientToScreen(hMainWnd,&p1);
ClientToScreen(hMainWnd,&p2);
//copythetwopoints'databackintotherect
rect.left=p1.x;
剩余18页未读,继续阅读
资源评论
- gametiger2014-08-06还不错,比较老
- fukainankai2013-03-01开发者论坛的原文,资源分少的朋友下载前慎重,
pbxlvym
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功