游戏编程之十四 游戏使计算机的发展超越了晶体管时代

DirectDraw 游戏编程基础(1)


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


 1. 简介
 2. 使用 DirectX 3 SDK的基本环境
 3. DirectDraw API
 4. DirectDraw, OLE, 和COM接口
 5. DirectDraw 起步
 6. DirectDraw 的基本知识 (DDEX1)
 7. 例一的扩展(DDEX2和DDEX3)
 8. 生成简单的动画(DDEX4和 DDEX5)
 9. 检验Duel例子
10. 关于最优化(Optimizations)和规范化(Customizations)
11. 下一步你应该干什么
  
简  介
DirectDraw是微软新近发行的DirectX 3软件开发工具箱(SDK)中的一部分。对那些不甚了解的人来说,DirectX 3 SDK是原来称为游戏SDK的最新版本。和在游戏SDK中一样,DirectX 3 SDK包含了一组动态链接库,用来图形加速,3D图形服务,声音加速,扩展连接,游戏杆操纵以及CD-ROM自动化。
关于DirectX 3 SDK可以有很多的话题讨论,本篇只涉及如何用DirectDraw来编写游戏中的图形部分。尽管需要一些有关OLE和构件模型(COM)接口的基础知识,整个过程还是相当简单的。而且,所需的有关OLE和COM接口的知识也将在此讨论到。
读完本篇后,您就可以用DirectDraw来写简单的游戏了。在这里,我只想讨论如何使用最基本的DirectDraw函数。所举的例子仅涉及到全屏和翻页,不讨论如何在窗口中使用DirectDraw,在3维图中使用文字,使用视频剪接或是用Direct3D生成表面。如果对这些内容感兴趣,可以参阅有关的文档。
使用 DirectX 3 SDK的基本环境
DirectX 3 SDK可以在Windows 95或Windows NT4.0中使用。基于本文的目的,假定使用的环境是IBM PC和Windows 95.另外,还需要安装DirectX 3 SDK,以便编译连接应用。
同时,使用的C或 C++ 编译器应能生成32位的应用。您也可以使用其他的语言,但这里并不想涉及。当然您还应当具有Windows的编程技术。 
  如果使用的是C编译器,则还必须包含Win32 SDK。Win32 SDK包含了生成可执行程序时的一些库。
DirectDraw API
DirectDraw是整个软件开发工具箱的一个构件。DirectDraw是为速度而设计的,它绕过与Windows的图形设备相连的多个层次,直接与硬件的底层打交道。这很适合游戏编程来,因为它着重于快速产生平稳的图形。 
但DirectDraw最重要的一点在于它对不同的显示适配器具有一个共同的接口。您不必管您的程序它是否会工作。DirectDraw利用包含在硬件抽象层(HAL)中的信息来决定显示适配器的功能。(HAL是由显示适配器厂商提供的)HAL为不同的硬件厂商和使用.DirectDraw的开发者提供了共同的接口。
然而,DirectDraw并不只限于利用显示适配器的硬件功能。如果您的程序指定了某一种特定的显示适配器,例如XXXX hardware blitter,但用户并没有该硬件,程序就会使用DirectDraw的硬件仿真层(HEL)。在这种情况下,DirectDraw利用内建的硬件仿真来仿真缺少的硬件。
图一说明了DirectDraw和其他Windows显示构件的联系。








图1. DirectDraw和其他Windows显示构件
DirectDraw API由DirectDraw对象组成,它表示具体的显示适配器。另外,DirectDraw API还包括表示surface的DirectDrawSurface对象,表示surface调色板的DirectDrawPalette对象和表示剪接列表的DirectDrawClipper对象。可以用DirectDraw对象来创建DirectDrawSurface和DirectDrawPalette对象。(也可用DirectDraw对象来创建DirectDrawClipper对象,但该剪接对象也可被独立地创建。这就涉及到另外的话题了。)创建全屏游戏要用到的只是DirectDraw,DirectDrawSurface和DirectDrawPalette对象。
    要了解这些对象是如何工作的,必须对OLE和COM接口有基本的了解。COM接口是所有DirectDraw编程的基础。下一节将讨论COM接口,如果您熟悉OLE,则可跳过它。


DirectDraw, OLE, 和COM接口
DirectDraw是围绕着OLE和COM接口来设计的。如果您不熟悉OLE编程,那将很难开始用DirectDraw编程,这是最基本的一点。尽管在很多书上解释了很多概念,介绍OLE和COM接口是如何工作的,但要用好DirectDraw其实只要了解有限的一些。
首先看看OLE和COM的定义。OLE是微软为在不同的进程和机器间共享信息和服务而引进的基于对象的技术。COM指的是构件对象模型,在OLE编程中,它是接口模型。知道这些概念后就可不理它们了,因为这对我们编程并不重要。我们要继续深入的是为用好DirectDraw所需了解的COM接口的最少的知识。
从本质上说,COM接口由三个成员组成:对象,接口和方法。对象实质上是一个黑箱,不需要管它里面是什么,因为我们只是通过接口来与它打交道。而要完成这一过程,通过的则是方法。如果您有一些硬件知识的话,可以把一个对象想象成一集成电路。与集成电路(对象)通讯是通过管脚(接口)来发送或接收信号(方法)。
所有的COM接口都是从OLE的Iunknown接口派生来的。通过保持Direcdraw对象的引用次数,Iunknown接口维护对象的生存期。另外,它提供了决定对象可用接口的方法。Iunknown接口由三种方法组成:AddRef,Release和QueryInterface。 
  AddRef和Release负责保持对象的引用计数。当创建了一个对象的实例时,对象的引用计数设为1。只要函数返回了对象接口的指针,该函数必须通过得到的指针调用AddRef,将引用计数增加1。(另外,当另一个应用与该对象相连时,引用计数也要加1。对我们来说,这一点并不重要,因为我们并不将其他的应用连到游戏上。)
  当用完一个接口后,要通过指针来调用Release,将引用计数减1。要收回一个对象时,它的引用计数必须为0。当对象的引用计数为0时,对象将被消除,它所有的接口都无效了。
  第三个方法,QueryInterface,查询对象是否支持指定的接口。如果对象支持,则返回指向接口的指针。
  AddRef,QueryInterface,和Release是如何与DirectDraw相连的呢?首先,我们没有理由在只用DirectDraw的简单游戏中使用AddRef和QueryInterface。DirectDraw创建了函数来负责增加引用计数并返回指向接口的指针。但您仍要对没一个隐式创建的接口指针执行Release操作。如果没有维护好对象的引用计数,将很容易引起内存泄露。在后面编码的例子中,将介绍如何进行。(也可在将应用与另一应用使用的DirectDraw对象相连时,使用AddRef和QueryInterface。同样,如果使用Direct3D,就不得不用QueryInterface来返回指向Direct3D接口的指针。这些内容都不在此讨论。)
  下面看一个使用IDirectDraw接口方法的C程序行。
Ddrval = lpDD->lpVtbl->SetDisplayMode( lpDD, ScreenX, ScreenY, ScreenBpp );


  程序用了SetDisplayMode方法来设置显示模式,返回值表示成功或失败。在此重要的一点是如何取得指向方法的指针,不能直接访问IDirectDraw接口方法。当一对象实例化时,它生成一个虚函数表,称为vtable,它包含了指向该对象接口方法的所有指针。在上例中,指向DirectDraw对象的指针(lpDD)指向了指向vtable的指针(lpVtbl),vtable中包含了对象所有方法的指针,具体地说,本例中指向了SetDisplayMode方法。应用和方法接口间的联系可以清楚地看成这样: 


 


  下一个例子看看如何用C++来做:  
ddrval = lpDD->SetDisplayMode( ScreenX, ScreenY, ScreenBpp );
    注意vtable不再显式地使用,C++自动地将对象(lpDD)作为第一个参数。不需要this指针,因为C++用指向当前对象的指针(本例中为lpDD)隐式地执行该方法。 
  如果想要了解更多的关于OLE和COM接口的知识,可以参阅Kraig Brockschmidt写的“Inside OLE”(可在MSDN中得到)。这是我所知的关于OLE和COM的最好的书。我推荐您去阅读该书的第一部分和第二部分的前半部分,以对COM接口有一个清楚的了解。这对您很好地理解DirectDraw和COM接口间的关系就已足够了。 
开始使用DirectDraw
    前面已经说过应当安装了DirectX SDK和C或C++编译器。在这我们假定使用的是Microsoft Visual C++ 4.0,并已安装在缺省的目录下。如果使用的是其他的编译器或软件安装在其他的目录下,则必须对下面的例子做相应的修改。
由于所涉及的是DirectDraw的基本知识,因此这里使用的例子都是关于DirectX 3 SDK的简单例子。它们示例了如何设置DirectDraw以及使用DirectDraw方法来执行简单的操作。学完这些例子后,你将能比较容易地理解DirectX 3 SDK光盘上所带的更为复杂的例子。
在正式开始前,还必须设置好编译环境,这取决于你将如何使用Visual C++来编译这些例子。我将示范如何用Microsoft Developer Studio来设置这些环境,或是在命令行下使用NMAKE。 
安装微软开发工作室(Micorsoft Developer Studio):
    Visual C++为那些喜欢使用接口的程序员提供了微软开发工作室(Microsoft Developer studio)。在开始编辑例程Directx 3 SDK前,需要打开一个新project 工作区,然后插入适当的文件,再设置一系列的环境变量参数,以使编辑器能够找到正确的库文件和头文件。下面我们要讨论例程DDEX1。以下所列步骤说明如何创建DDEX1:
     当你打开Microsoft Developer Studio 后,可使用以下步骤来创建project工作区:
     1. 在菜单 File 中,选择选项New。
     2. 在新对话框中,选择 Project Workspace(项目工作区),然后单击 OK。
     3. 在Type list 中选择选项 Application。
     4. 在Location box(搜索框),你可以通过选择一个路径来查找你所需的项目
     5. 在 Name 文本框中,键入DDEX1。
     6. 单击Create后,一个名为DDEX1 Classes 的新文件夹出现在工作区窗口的
   左部。
     这样你就创建好了一个项目工作区,使用以下步骤使你在该工作区插入一个适当的文件:
     1. 在菜单 Insert 中,单击选项 Files Into Project。
     2. 浏览目录:DXSDK\SDK\SAMPLES\DDEX1,并选择该目录下的所有文件。
     3. 单击 Add 选项,则工作区窗口左侧的文件夹就会变成DDEX1。
     4. 单击folder name(文件夹)左侧的"+",可查看到DDEX1文件夹中的文件列表。
     为了能够正确地编辑和链接 DirectDraw 例程,还需完成以下步骤为头文件设置正确的路径:
     1. 在菜单 Tools 中,单击 Options,则Options对话框就会被击活。
     2. 选择 Directories 选项。
     3. 在列出的目录中,选择头文件所在的目录。
     4. 在目录框中,双击列表底部的空白行(以长方形表示),然后键入:  C:\DXSDK\SDK\INC。
     5. 按回车键。
     6. 在目录框中,双击列表底部空白行并键入: c:\DXSDK\SDK\SAMPLES\MISC。
     7. 单击 OK 选项。
     接下来,按以下步骤为库文件选择路径:
     1. 在目录列表框中,选择库文件所在的目录。
     2. 选择 Link 选项
     3. 在目录下拉盒中,找到 General 选项
     4. 在 Objext/library 模块下拉盒中,加入 Draw.lib 和 Winmm.lib
     5. 单击 OK 选项。


     上面所列出的大多数步骤在创建新 Project 的过程中都会用到。其中目录路径和链接模块被永久地加入到环境参量中。
      为 NMAKE 设置路径:
      如果你更喜欢使用 NMAKE,你需要为库模块和头文件设置正确的路径。下面列出了 Visual C++ 4.0 所用到的所有路径:
      @echo off
      set path=c:\MSDEV\BIN;%PATH%
      set
      INLUDE=C:\MSDEV\INCLUDE;C:\MSDEV\MFC\INCLUDE;C:\DXSDK\SDK\INC;%I
      NCLUDE%
      set LIB=C:\MSDEV\LIB;C:\MSDEV\MFC\LI;C:\DXSDK\SDK\LIB;%LIB%
      set INIT=C:\MSDEV\;%INIT%
       在批处理 autoexec.bat 中加入以上各行,并重新启动计算机,你就可以方便地编辑你的程序了。(如果你使用的是Microsoft Visual C++ 2.0, 则你需要把上面的 MSDEV 改为 MSVC20,且其他路径均不变)
       为了实际编辑一个程序,进入该程序子目录(例如:C:\DXDSK\SDK\SAMPLES\    DDEX4),并键入:
       NMAKE
       这将在当前目录下创建一个DEBUG子目录,并且在该子目录下生成可执行文件。

你可能感兴趣的:(游戏,计算机,时代,游戏编程,晶体管)