⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2d.txt

📁 一个2D游戏引擎设计的完整文档
💻 TXT
📖 第 1 页 / 共 2 页
字号:
上一次我写了一个史上最简单的Windows程序。很不幸,在计算机的世界里最简单的也是最愚蠢的东西。如果一个程序什么也不做的话那它就没有脸面再存活在这世界上,所以为了让我的作品能够有更多生存的空间我必须加入一些有意思的东西。DirectDraw虽然只是一段很短的代码但却能彻底地改变人们对这个愚蠢作品的看法。

可能并不是每个人都明白什么是DirectDraw,其实它是DirectX的一部分。一看它的名字也大概猜到它是用来画图之类的。不管用来干嘛,先看看著名的John De Goes 在他的名著《3D GAME PROGRAMMING WITH C++》里对DirectX的定义。

DirectX is a software development kit (SDK) specifically to promote hardware assisted, high performance games for Windows, consists of many components...

The components of DirectX are divided into two groups: DirectX Foundation contains low level components that supply basic functionality; DirectX Media contains high level components that perform many complex operations.

这是他的原文,为了让一些英文不太好的朋友不必浪费时间去翻词典我将其翻译一下,这没有任何商业目的,所以请别告我侵权。

DirectX是一个开发软件特别用于提高硬件协助能力以支持高质量的Windows游戏。

DirectX有两组组件:DirectX基本库,包含低级组件用于基本功能;DirectX媒体,包括高级组件用于完成许多复杂的操作。

以上文字好象有点隐晦难懂。其实我对上面的英文的理解也就相当于上面这段中文的水平。虽然John De Goes的这本书被公认为3D游戏的教材,而且我的偶像Andre LaMothe还特地为这本书写了序但我在看这本800页的英文书时常常被许多类似于上面的文字搞的头昏脑胀。

讲了这么多你可能还是没明白我到底要说些什么,不要着急,所谓心急吃不了热豆腐,特别是美女的豆腐。再看看下面的文字。

DirectX Foundation consists of the following components: DirectDraw, DirectSound, DirectMusic, Direct3D Immediate Mode (IM), DirectInput, DirectSetup, and AutoPlay.

DirectDraw provides a way for software developers to access the display's attributes - including the size of the desktop and how many colors can be displayed at once - and the display's features, such as playing back video, displaying images and bitmaps, and so on. DirectDraw is not graphics library, in that it cannot draw lines, polygons, or text, but it is still nonetheless for today's 3D games.

这段比较好理解,我也照着翻译:

DirectX 基本库包括:DirectDraw, DirectSound, DirectMusic......(参见英文)

DirectDraw 提供了一个方法给软件开发人员进入显示的属性——包括桌面的大小和能被显示的颜色数——显示特征,列如播放后台视频,显示图象和位图,等等。DirectDraw不是图形函数库,也就是说它不能画线,多边形,或文字,但是它并非对今天的3D游戏毫无用处。

天啊!为什么译成中文后反而看不太明白了!看来我还是不适合当翻译。所以大家将就点,反正就是那个意思,用一句教我软件工程的老师Mr. Christopher常挂在嘴上的话“你明白就是明白,不明白就是不明白”

哈,如果真不明白的话,就忘掉上面所有的废话(forget these bullshit)。这完全没有关系,我保证如果你看完本文后能从地狱爬回来而且能解释的比我更好的话,你就可以毫不客气地揍我一顿。

从程序员的角度来说,DirectDraw是一个很复杂的类。不必管它到底是什么,反正你如果要使用DirectDraw, 首先必须创建一个DirectDraw的对象(object)。也就是说声明一个DirectDraw变量。用下面的代码:

LPDIRECTDRAW lpDD; //LPDIRECTDRAW 就是微软写的DirectDraw类的指针类型。

有了这个变量后就可以对DirectDraw进行初始化:

HRESULT Result;

Result = DirectDrawCreate( NULL, &lpDD, NULL);

DirectDrawCreate函数用来初始化DirectDraw的对象(object),这个函数有三个参数,它的原型如下:

HRESULT WINAPI DirectDrawCreate(

GUID FAR *lpGUID,

LPDIRECTDRAW FAR *lplpDD,

IUnknown FAR *pUnkOuter);

lpGUID:一个指向GUID(Globally Unique Identifier)的地址变量,它描述了一个用于在其上面创建DirectDraw的驱动器。如果这个变量为NULL那么就是说使用当前的显示驱动程序。

lplpDD:就是上面的lpDD的指针。

pUnkOuter:微软说这是用于将来对COM的兼容而设定的参数,但微软又说如果这个变量不为NULL的话,将返回一个错误。所以如果你不是反微软联盟的成员的话就给它NULL吧。

如果初始化成功的话函数返回的值为DD_OK。

初始化成功后就可以设定Cooperative Level(应该是合作层之类的意思吧,反正就是指定游戏是运行于窗口模式还是令人激动的全屏模式)。

调用SetCooperativeLevel函数:

Result = lpDD->SetCooperativeLevel(

GetActiveWindow(),

DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);

此函数的原型为:

HRESULT SetCooperativeLevel(

HWND hwnd,

DWORD dwFlags);

参数说明:

hwnd:要设定窗口的句柄。

dwFlags:这包括很多莫名其妙却非常有用的标志。最常用的当然是DDSCL_FULLSCREEN和DDSCL_NORMAL分别指定全屏模式或普通窗口模式。DDSCL_EXCLUSIVE表示该窗口独占所有操作。DDSCL_ALLOWREBOOT当然就是指可以让你重启电脑,就是不将Ctrl+Alt+Del给屏蔽掉。至于其他标志可参考MSDN,当然如果你有的话。

同样,函数成功将返回一个DD_OK。

如果将窗口模式设为全屏的话,可以设定显示模式:

Result = lpDD->SetDisplayMode(800, 600, 32);

if(Result == DD_OK)

{/*Display mode was set*/}

else

{/*Display mode was not set*/}

很显然可以通过一个SetDisplayMode的函数来设定显示模式,大家一眼就能明白上面的代码将显示模式设成800*600颜色数为32位。还是在看看该函数的原型:

HRESULT SetDisplayMode(

DWORD dwWidth,

DWORD dwHeight,

DWORD dwBPP,

参数说明:

dwWidth:屏幕宽度。

dwHeight:屏幕高度。

dwBPP:颜色的位数。

好了,请注意,下面我要说的是DirectDraw的精华,创建一个主页面。听起来好象没什么了不起,但我们玩游戏所看到的图象正是画在这个主页面上的。它其实是一段显卡上的内存。DirectX允许我们直接向这段内存里写数据。这意味着显示速度将会大大的提高,如果你开发一个射击游戏,那么玩家就不必在发出子弹后要一边泡咖啡,一边等待子弹命中目标了。看下面的代码:

LPDIRECTDRAWSURFACE lpDDPS; //声明一个DirectDrawSurface的对象的指针。

DDSURFACEDESC ddsd;//创建一个DDSURFACEDESC对象。

ddsd.dwSize = sizeof(ddsd); //指定该结构所占的内存字节数。

ddsd.dwFlag = DDSD_CAPS; //使ddsCaps成员有效。

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; //指定为主页面。

Result = lpDD->CreateSurface(&ddsd, &lpDDPS, NULL); //创建这个页面

我敢肯定这是本文里最让人迷惑的代码。但不必担心,我会使出吃奶的力气来将其解释清楚,虽然我并不喜欢喝牛奶。

首先大家要明白一个概念,什么是DirectDraw页面?这其实就是一个页面,类似于一张白纸,你可以在上面画任何东西。在做游戏时所有的图象都是画在不同的页面上,将某一个页面复制到主页面去就能立即在屏幕上看到这些图象。

我们来看看那个似乎比长城还长的类型名LPDIRECTDRAWSURFACE,它的意思是lp(long point)-DirectDraw-Surface,就是一个指向DirectDraw页面的长指针。这里声明了一个变量lpDDPS我用该变量来代表我要创建的主页面。记住这最好是个全局变量。

然后我还要声明一个ddsd的变量,它的数据类型是DDSURFACEDESC。DDSURFACEDESC其实是DirectDraw Surface Description的缩写。意即DirectDraw页面描述。这是一个用于描述页面的结构。我们定义了这个结构的对象ddsd后就可以对其进行填充,比如指定它为一个主页面。

ddsd.dwSize就是ddsd所占的字节数,记住在你使用DDSURFACEDESC之前一定要填充这个数。不过这是我所见过的最滑稽的赋值运算。好比在说“我的身高等于用尺子量我的身高所得到的长度”!

ddsd.dwFlag是控制标志,这里让它等于DDSD_CAPS意思是让ddsd结构里的ddsCaps成员有效。而ddsCaps是DDSCAPS结构,它包含着一些页面性能的描述。

ddsd.ddsCaps.dwCaps里有许多高级和复杂的设定,比如是否为3D页面,是否具备Alpha特性等等。但现在我们只需要指定该页面为主页面。

最后用CreateSurface函数来创建这个页面。

函数原型:

HRESULT CreateSurface(
LPDDSURFACEDESC lpDDSurfaceDesc,

LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface,

IUnknown FAR *pUnkOuter);
参数说明:

lpDDSurfaceDesc:当然是DDSURFACEDESC的指针变量。

lplpDDSurface:一个指针变量指向那个页面指针变量。

pUnkOuter:不用说又是微软的陷阱,如果不想掉进去摔个粉身粹骨就放NULL吧。

好了终于完成了,现在你可以在屏幕上写字了,或者调入一幅bmp的位图。记得前面尊敬的John De Goes 说过DrectDraw并不能用来画点或画线,但实际上可以做到。我无意冒犯Geos先生,只不过电脑实际上是个傻瓜而已,无论它多么铁面无私不讲人情只要一点点技巧往往就能瞒天过海。不过这不是我今天要透露的秘密。还是先写两个字上去吧。

HDC hDC;

if(lpDDSP->GetDC(&hDC) != DD_OK)
return FALSE;
SetBkColor( hDC, RGB( 0, 0, 255 ) );
SetTextColor( hDC, RGB( 255, 255, 0 ));
TextOut( hDC, 220, 200, "Yes, I did it!",14);

LPSTR lpMesg;

lpMesag = "Press Esc to exit";
TextOut( hDC, 280, 240, lpMesg, lstrlen(lpMesg));
lpDDSP->ReleaseDC(hDC);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -