首页>
技术资讯>
详情

详细讲解DirectDraw编程基础

2016-05-30 来源:CloudBest 阅读量: 704
关键词: 程序设计


  本文面向有几个月学习编程经历的初学者:看过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中,这是个全局变量

热门推荐 查看更多