分享
 
 
 

详细讲解DirectDraw编程基础

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

本文面向有几个月学习编程经历的初学者:看过C++的教程,看的懂基本的C++语法;有点点VC使用经验,知道怎么去组建一个工程;理解一些windows编程的基本概念,比如窗口、消息循环等;还有,不懂的地方会去查资料:)。

看过几本关于DirectDraw的书,这些书都不错,在此感谢她们的作者。美中不足的是这些书的部分起点较高,虽然我们仍然能够清晰的理解一些概念,但在组织这些文件上会有不少困惑。在此我重申一下书中的概念,也借此梳理一下自己的思路。废话少说,言归正传。

首先说一些不可不说的东西。我认为它们不可不提,是因为这些东西也许太基础,高手们往往忽略这些东西对新手的作用。作为一个新手,我觉得掌握程序的框架及组织方法,比多熟悉几个APIs更迫切一些。Now lets begin:

写一个游戏程序,要熟悉其流程,另外要锻炼组织程序文件的能力。对新手来说,我建议按部就班的来处理及分析要写的程序,不主张这个时候你在搞思维跳跃。这是个良好的习惯,当然也有利于我们尽快掌握编程的思想方法。下面来看一个概括的流程及相应的程序框架

(框架显示不出来。。)

那么,如何利用上面的流程来构建我们的大体程序框架呢?

我们已经知道一些windows编程方面的东西了,也许你还比较了解MFC。我们这里不提倡用MFC,尽管它封装了好多有用的模式,但对我们编游戏来说,倒是累赘了。好,接着说。既然采用windowsAPI,可以建立个文件WinMain.cpp来处理windows编程中有关窗口的一些问题。这样,我们在该文件中应该完成创建窗口,处理基本消息(比如按“esc”退出等),控制程序退出等。游戏过程中窗口的消息是不是也要在这处理呢?当然,不过游戏当中的窗口就不仅是windows窗口了,显示部分要靠DirectDraw来控制,那么我们只好在WinMain.cpp中调用相关的模块来处理。这么看来,在WinMain.cpp中几乎囊括了整个流程,不错,它就控制了程序的整个框架,为你的程序内核提供了一个平台。平台有了,那么下一步,GameMain.cpp要诞生了,这个主要用来控制整个游戏的各个组件,协调各部分工作,完成游戏设置初始化,游戏中消息循环,控制游戏退出。你的才华就在这儿来尽情的发挥了。一般,游戏程序会有几个固定的组件的:显示,音乐,信息输入。在DirectX中提供了很方便的组件DirectDraw,DirectSound和DirectMusic,DirectInput。相应的我们建立MyDirectDraw.cpp,MyDirectAudio.cpp,MyDirectInput.cpp来控制各部分组件的相应功能。

显然,这3部分都是为GameMain.cpp服务的,被GameMain.cpp调用。那么我们可以看出我们的程序应该包括的文件及其包含关系为:

(图表显示不出来了,555)

程序文件怎么去组织,应该由这个表可以看出来。这么一看,我们发现,WinMain.cpp好像是一个投资者,提供开发平台,他只关注整个项目总的进程,不关注细节。GameMain.cpp好像个项目负责人,整个项目的细节过程由他来策划,来控制,向上与WinMain.cpp交互,来完成项目,向下协调MyDirectDraw.cpp,MyDirectAudio.cpp,MyDirectInput.cpp之间的工作。MyDirectDraw.cpp,MyDirectAudio.cpp,MyDirectInput.cpp这三个家伙就是员工了,负责各自的工作,完成相应的功能给GameMain.cpp。

组织程序应该就是这么个思路,当然具体问题具体分析。那么我们下面来开始看DirectDraw部分了。

首先,做准备工作,安装DirectX SDK,在VC中添加dxguid.lib和ddraw.lib(本来不想说这个,看到有个教程,它少加了dxguid.lib,郁闷了我好一阵子,害人颇深感觉)这样,directdraw程序才能通过编译。提一下,dxguid.lib中定义了DirectX中会用到的所有全局句柄,ddraw.lib是DirectDraw使用的函数库。

下面就可以写代码了,这里我们当然主要看MyDirectDraw.cpp该怎么写了

为此,我选出了几个源代码,做参考研究,它们会与本文一起打包。

我还是习惯先从整体上鸟瞰一下:

一般,在MyDirectDraw.cpp(注意不要忘记引用头文件ddraw.h)中至少要有两部分:初始化和结束。先看初始化,所谓初始化无非是个准备工作,需要的东西定义创建出来摆在手边以备后用。来看看初始化函数intMyDirectDrawInit(void)该怎么写。首先定义一个指向DirectDraw对象的指针,创建DirectDraw对象,查询以获取最新的DirectDraw接口,设置协作等级,设置显示模式。通过这些步骤可以创建一个黑色的屏幕了,也就是说已经开辟了我们需要的空间了,当然DirectDraw程序的初始化不会这么简单。要操作2d图形,我们还要接着创建主页面和缓冲页面以及离屏页面,总之根据需要,凡是需要在操作前需要准备好的东西都可以放在这里。那么结束 int MyDirectDrawShut(void)就应该释放我们开辟的东西,一般要释放主页面指针,和DirectDraw接口等。

大体就是这么个样子,go on,该细一点了,呵呵

先定义指针:LPDIRECTDRAW lpDDraw_temp;代表整个显示系统

创建对象: if (FAILED(DirectDrawCreate(NULL, &lpDDraw_temp, NULL)))

{

MessageBox(NULL,TEXT("Direct Draw Create error!"),

TEXT("Wrong!"),MB_OK);

return(0);

}

这里用了一个FAILED宏来检测是否创建成功,这可以帮我们跟踪错误。

函数DirectDrawCreate(NULL, &lpDDraw_temp, NULL)完成创建,第一个参数是显示驱动的全局唯一标志符,这里null表示目前的显示设备;第二个参数用来接受创建出来的DirectDraw对象地址,这里用&lpDDraw_temp接受;第三个参数?不要问,就给它null,不想惹麻烦的话。

查询DirectDraw接口:if(FAILED(lpDDraw_temp-QueryInterface(IID_IDirectDraw7, (LPVOID *)&lpDDraw7)))

{

MessageBox(NULL,TEXT("DirectDraw QueryInterface error!"),

TEXT("Wrong!"),MB_OK);

return(0);

}

通过QueryInterface()方法来获取新接口,这里是IDirectDraw7而不是IDirectDraw8,指向IDirectDraw7的指针放在lpDDraw7中,这是个全局变量,可以这样定义LPDIRECTDRAW7 lpDDraw7=NULL;

顺便说一下,一般情况下你是应该知道你使用的接口的,这和SDK有关,所以说这一步不是必须的。

设置协作等级: if (FAILED(lpDDraw7-SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))

{

MessageBox(NULL,TEXT("DirectDraw SetCooperativeLevel error!"),

TEXT("Wrong!"),MB_OK);

return(0);

}

决定你这个程序和windows的关系,它向windows申请所用资源,比如它要全屏,独占等。第一个参数是主窗口句柄,就是你WinMain()中创建的那个了,第二个参数有几个控制标志,常用的用法如下:

DDSCL_FULLSCREEN:全屏模式,必须和DDSCL_EXCLUSIVE同时使用

DDSCL_EXCLUSIVE:请求独占级别,须和DDSCL_FULLSCREEN同时使用

DDSCL_ALLOWREBOOT:允许系统检测ctrl+alt+del按键消息(这很有用)

我想,这三个就够用了,其他的就先不用管了

设置显示模式:if(FAILED(lpDDraw7-SetDisplayMode(800, 600, 16,0,0)))

{

MessageBox(NULL,TEXT("DirectDraw SetDisplayMode error!"),

TEXT("Wrong!"),MB_OK);

return(0);

}

游戏中要使用的显示模式可能和用户当前显示模式不一样,要在此统一设置SetDisplayMode()强制使用它设置的模式,它的前三个参数很容易懂吧,第四个,用0表示使用默认的刷新率,第五个参数这里是0,有书上说必须用DDSDM_STANDVGAMODE(可以理解,只是不知道这个0什么意思,我想应该是default的意思吧。

到此为止,我想已经创建出来我们需要的空间了,以后,随着我们要求的提高,再逐步完善初始化函数,now看看结束函数:

释放接口: if (lpDDraw7)

{

lpDDraw7-Release();

lpDDraw7 = NULL;

}

以后还要释放主页面,缓冲页面等,需要注意一点的是一定要释放你申请的资源,这是个好习惯,更应该注意的一点是先创建的一定要后释放,因为后创建的可能是在先创建的环境下工作的。

到此为止,我们只是做好了最基础的准备工作,什么还都不能做呢

想做点什么吗?歇会吧,说点不得不说的题外话:

那么我们来看看颜色吧。有关色彩,分这么几种,256色(8位的),16位增强色,24位真彩和32位真彩。256色估计很少用了,16位目前还是主流,所以我们着重看一下16位增强色,通常16位增强色有两种格式:5.5.5和5.6.5,一般用RGB表示法表示。其中:

5.5.5格式,最高位为Alpha位,表示是不是透明,其余15位表示颜色,红绿蓝各5位,这种格式可以表示32786种颜色。通过宏

#define _RGB16BIT555(r,g,b)((b%32)+((g%32)

对5.6.5格式,显然,红蓝各5位,绿6位,这样可以表示65536种颜色,同样,宏

#define _RGB16BIT565(r,g,b) ((b%32)+((g%64)

中间的移位我也搞不清楚是怎么回事,姑且先不看了,看的越多可能越胡涂哦

那么到底该用哪种格式?看机器了,大部分可以用5.6.5,当然你可以检测一下,至于怎么检测嘛,我就不说了,查查相关资料就可以了。24位呢?红绿蓝各8位呗,32位?添个Alpha位,其余同24位。好了颜色就说到这里。

下面想干嘛?想在屏幕上搞点颜色出来,参看附的源代码code1

你会不会发现我们还应该在上面的基础上添点什么?对

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有