作者:Johnny Watson 译者:蓝色feel From:www.x-temple.com
这篇文章描述了怎样通过使用DirectX SDK中的通用库文件来轻松地建立一个 DirectDraw对象及其显示表面(surface)。(这篇文章)对那些想要在不破坏原应用程序架构的情况下快速掌握它来做些事的人特别有帮助,请注意事实上这些类中抽象了相当多且复杂的事物,因此我强烈地推荐你在掌握它们功能的同时,尽量关注一下其底层的实现,这样有助于你尽快掌握它们的工作方式。
1.DirectDraw的安装
在本文中,我假定你拥有微软公司的 Visual C++ , 和 DirectX 8.1 SDK。如果没有,就快去准备一份吧。 首先,启动你的 Visual C++, 创建一个新的 Win32 应用程序工程。 然后进入 你 DirectX SDK 文件夹中的 multimedia\common\include 目录 , 拷贝 dxutil.h 和 ddutil.h 至你新建工程的目录下。 然后将你 DirectX SDK文件夹中的 \multimedia\common\src目录下的dxutil.cpp 和 ddutil.cpp 也拷贝至你新建工程的目录下。把四个文件加入你的工程, 然后连接上下列库文件: dxguid.lib ,ddraw.lib,winmm.lib。现在,你创建一个新的 C++源文件文件, 而且也把它加入你的工程。 这些是整个教程中我们将会用到的工作文件。
2.DirectDraw程序代码
既然我们已经准备好了, 让我们开始写一些代码什么的实在的东西吧!
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "dxutil.h" #include "ddutil.h"
这是标准的代码。#define WIN32_LEAN_AND_MEAN,这句的目的是指示编译器不要包含与MFC相关的操作。( 只是一个好的练习——如果你不在使用 MFC) 然后我们包括 dxutil.h 和 ddutil.h,这是两个很有用的头文件。 他们能够使你以一种比通常的DirectX编程更轻松的方式来工作。
//globals
bool g_bActive = false;
CDisplay *g_pDisplay = NULL; CSurface *g_pText = NULL;
//function prototypes
bool InitDD(HWND); void CleanUp(); void GameLoop();
代码自身说的很清楚,不是吗?我们的第一个全局变量,g_bActive,是一个让我们的应用程序知道是否应该运行游戏的标志。 如果我们没有这个全局变量, 我们的应用程序可能在它自己被注销之後还在尝试着在我们已经创建的 DirectDraw 的表面上画点儿什么呢!虽然这通常是一个在程序结束的时候出现的一个不大的问题,但它会导致一个非法操作的错误,我们并不想那样,不是吗? g_pDisplay 是我们的显示对象。CDisplay 在 ddutil.h 中是最主要的类。它控制着我们前后的缓冲区,并提供一些针对该缓冲区的功能,如访问及存储缓冲区,将表面写入缓冲区,创建一个表面,等等。 g_pText 是一个文本表面。 我们将会在这个表面 (你或许已经有所理解 ) 之上写文本, 然后将它传送到我们的屏幕之上。 注意它们两者都是指向对象的指针, 而且被初始化为NULL。 现在来看看函数的原型。 InitDD() 只是用来初始化 DirectDraw 。 多亏了 DirectDraw 的通用文件(common files),这还算是一个简单的程序。( 但是晚些时候我们才会接触到它们) CleanUp()调用了对象 g_pDisplay 的析构函数来释放 ( release)我们所创建的DirectDraw对象及其表面。很明显, GameLoop() 则是将来用来放你的游戏的地方。
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_CREATE: InitDD(hWnd); g_bActive=true; break; case WM_CLOSE: g_bActive=false; CleanUp(); DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_MOVE: g_pDisplay->UpdateBounds(); break; case WM_SIZE: g_pDisplay->UpdateBounds(); break; default: return DefWindowProc(hWnd,uMsg,wParam,lParam); break; } return 0; }
这里是标准的 Windows 程序消息处理机制的代码。 当产生 WM_CREATE 消息时,我们初始化 DirectDraw, 并将我们的全局变量 g_bActive 设定为true,这样就可以执行游戏循环 GameLoop() 了。当消息 WM_CLOSE 被传递的时候,我们就把全局变量 g_bActive 设定为 false ( 这样我们的应用程序就不会在它自己被注销之後还在尝试着向我们已经创建的 DirectDraw 的表面上写数据了)。然后调用 CleanUp() 函数,最终注销我们的窗口程序。处理 WM_MOVE 和 WM_SIZE 事件非常重要,因为若处理不当,DirectDraw 将不顾窗口本身是否已经被移动或重新设定其大小,仍然在屏幕上原来的位置上继续作画,从而造成错误。
bool InitDD(HWND hWnd) { //dd init code g_pDisplay = new CDisplay();
if(FAILED(g_pDisplay->CreateWindowedDisplay(hWnd,640,480))) { MessageBox(NULL,"Failed to Initialize DirectDraw", "DirectDraw Initialization Failure",MB_OK |