用DirectDraw编写动画程序Word下载.docx
- 文档编号:19018913
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:36
- 大小:31KB
用DirectDraw编写动画程序Word下载.docx
《用DirectDraw编写动画程序Word下载.docx》由会员分享,可在线阅读,更多相关《用DirectDraw编写动画程序Word下载.docx(36页珍藏版)》请在冰豆网上搜索。
心中一定在嘀咕:
&
哼,原来是个江湖骗子,光说不练。
各位看官不要着急,不把这些基础理
论搞懂就去看下面的程序,你肯定是&
洋鬼子看戏&
mdash;
目瞪口呆&
。
首先,让我们先了解一下DirectDraw的三个重要概念。
1.表面
在用DirectDraw编写程序时,我们先要创建若干个图形数据缓冲区,并把这些图形数据
装入其中,再进行转换、拉伸、挎贝等操作,并且还可以显示这些缓冲区中的图形数据,
这些缓冲区就称为表面。
表面可以分为几类。
主表面(primarysurface)是用户在屏幕上可以看到的,它是显示内存的一部分。
所有
DirectDraw程序都有主表面,而且只有一个。
它在DirectDraw表面对象之前就已经存在了,
因此不能改变它的尺寸、格式和位置。
主表面有一个很重要的特性&
翻转。
页面翻转用于程序中,可以产生相当平滑、不闪烁的动画。
一个可以翻转的主表面实际上是
两个表面,一个是可见的,一个是不可见的。
不可见的表面称为后备缓冲区。
当发生表面
翻转时,后备缓冲区就成为可见的,而以前的可见表面则成为后备缓冲区。
还有一种表面叫离屏表面(off_screensurface),它是不能直接见到的。
离屏表面作
为存储缓冲区,有助于表面之间的互相切换,它的大小是可以改变的。
主表面和离屏表面都分为有调色板的和无调色板的这两类。
像素深度为8位(256色)的
表面称为有调色板的表面;
而像素深度为16位(64K色)、24位(16M色)的像素表面称为无调
色板的表面,它们存储实际的色彩值(RGB值)。
在本文下面的程序中,我们使用24位表面
即无调色板的表面。
2.Bltting
Bltting是用于复制图形的语言,可以将图像从一处拷贝到另一处。
例如大家所熟悉的
CDC类(设备描述表类)的BitBlt()就是具有这样功能的函数。
在DirectDraw中,典型的blt操
作是将离屏表面的内容拷贝到一个后备缓冲区,而一般的blt操作调用一个源表面和一个目
标表面,把源表面的内容拷贝到目标表面中,不仅可以整体拷贝源表面,而且还可以拷贝源
表面内的任何矩形区域到目标表面的任何位置。
blt还支持透明拷贝,就是指表面中的某一
像素在blt过程中可以不予以拷贝,而这个像素值是由色彩键码(DDCOLORKEY)决定的。
DirectDraw中有三个支持blt的函数,它们是Blt()、BltBatch()、BltFast()。
Blt()
用得最多,BltFast()的速度比Blt()要快,但功能却很有限,例如不支持拉伸、剪切等操作。
还有一个函数BltSurface(),它是DirectWin类的一个成员函数,Blt()、BltFast()更
具有适应性,并且使用起来更加简单。
例如,当我们把源表面拷贝到目标表面外时需要裁剪,
而BltFast()不支持裁剪。
这时我们使用BltSurface()函数,它在内部使用Blt()和
BltSurface()函数,并根据情况自动执行裁剪。
3.色彩键码
DirectDraw可以把某种颜色或某个范围的颜色指定为一个颜色值,这个颜色值是由
DDCOLORKEY结构即色彩键码说明的,DDCORLORKEY结构说明如下:
typedefstruct_DDCOLORKEY{
DWORDdwColorSpaceLowValue;
//颜色范围的低端
DWORDdwColorSpaceHighValue;
//颜色范围的高端
}DDCOLORKEY;
当我们对表面进行拷贝操作时,表面中哪些像素不被拷贝是由色彩键码决定的。
例如当
DDCOLORKEY结构的两个分量都为零时,表面内所有置为零的像素都不能被拷贝。
又例如,当
表面是24位RGB模式时,若想指定RGB=(120,120,120)像素不被拷贝,则应该:
DDCOLORKEYddck;
ddck.dwColorSpaceLowValue=RGB(120,120,120);
ddck.dwColorSpaceHighValue=RGB(120,120,120);
surf&
rarr;
SetColorKey(DDCKEY_SRCBLT,&ddck);
其中SetColorKey()函数是把色彩键码赋给表面surf。
这样,在对表面surf的blt操作期
间RGB值为(120,120,120)的像素不能被拷贝。
二.实践篇
古语云:
君欲善其事,必先利其器&
,在编写DirectDraw应用程序之前,
我们先要准备好以下工具:
Windows95、Windows98或WindowsNT4.0
DirectX驱动程序(最好是DirectX3.0以上版本)
DirectXSDK
VisualC++5.0
DirectSDK包括开发基于DirectX应用程序所需的全部文件,全部安装需要80几兆的硬盘
空间。
其实你只需安装必需的头文文件(.h文件)和库文件(.lib文件)就行了。
安装完DirectXSDK,需要通知VisualC++DirectXSDK的路径。
具体做法是:
在VC的
编译环境中,依次把Tools-Options-Directories中的ShowDirectoriesfor一栏中的
includefiles和libraryfiles中分别填入SDK的inc和lib目录,如图1所示。
再准备两幅bmp格式的位图,要求24位(16M色),其中background.bmp作背景,如图2;
另一幅bird.bmp作为子画面,如图3。
bird.bmp是由4幅小画面组成的,从左到右,从上到下,
分别为动画的1至4帧。
这样做的目的是避免过多位图文件带来的不必要的麻烦。
还要注意一
点的是子画面的背景要为黑色(RGB=(0,0,0)),因为在下面的程序中,色彩键码把黑色设为透
明色。
好,一切准备就绪,让我们开始吧!
进入VC5的编程环境,File-New-Project,选择DirectDrawAppWizard,输入项目名Fly,
按下Ok,以后每一步都按其缺省值即可,这样AppWizard就会自动创建一个项目Fly,属性如下
APPLICATIONSTYLE
Full-Screen
SETTINGS
640x480
16-bit
CLASSNAMES
FlyApp
FlyWin
CONTENT
Bitmap
这时,按&
Ctrl+F5&
编译运行,你就会看到一个&
三角形&
在
屏幕上撞来撞去。
在FlyWin.h中添加代码,如下所示:
#ifndefFLYWIN_H
#defineFLYWIN_H
#include&
DirectDrawWin.h&
classFlyWin:
publicDirectDrawWin
{
public:
FlyWin();
protected:
//{{AFX_MSG(FlyWin)
afx_msgvoidOnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags);
afx_msgintOnCreate(LPCREATESTRUCTlpCreateStruct);
afx_msgvoidOnTimer(UINTnIDEvent);
afx_msgvoidOnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
intSelectDriver();
intSelectInitialDisplayMode();
BOOLCreateCustomSurfaces();
voidDrawScene();
voidRestoreSurfaces();
voidCopySurface(LPDIRECTDRAWSURFACEts,
LPDIRECTDRAWSURFACEss,
intx,inty);
voidSplitSurface(LPDIRECTDRAWSURFACEts,
CRect&srcc,
intx,inty);
LPDIRECTDRAWSURFACEbksurf,//定义指向背景画面表面的指针
flysurf,//指向总子画面表面的指针
storesurf,//指向存储背景区域表面的指针
flysurf1,//指向第一帧子画面表面的指针
flysurf2,//指向第二帧子画面表面的指针
flysurf3,//指向第三帧子画面表面的指针
flysurf4,//指向第四帧子画面表面的指针
cursurf;
//指向当前移动的子画面表面的指针
//背景画面指background.bmp;
总子画面指bird.bmp
intx,y,nPreX,nPreY;
//定义子画面移动的坐标
intnIncX,nIncY;
//定义子画面移动的像素数
intnCount;
//定义计数器
DWORDfw,fh;
//定义总子画面的宽和高
};
#endif
其中,CopySurface()函数起保存被子画面覆盖掉的背景区域的作用。
参数ts是指向目标
表面的指针,ss是指向源表面的指针,x、y是源表面上需要拷贝的矩形区域左上角的坐标。
SplitSurface()函数用于分离一个大的总子画面表面为4帧小子画面表面。
参数ts是指向
目标表面的指针,ss是指向源表面的指针,srcc是源表面上需要选取的矩形区域,x、y要拷
贝到目标表面上的左上角坐标。
其实当我们看了下面FlyWin.cpp中这两个函数的原型后,细心的朋友也许会发现,两个
函数完全可以写成一个函数。
而本文特意写成两个函数,为的是程序的清楚易读,不易引起
混淆。
下一步在FlyWin.cpp中添加代码,如下所示:
Headers.h&
resource.h&
DriverDialog.h&
FlyWin.h&
#pragmacomment(lib,&
ddraw.lib&
)
dxguid.lib&
constDWORDdesiredwidth=640;
constDWORDdesiredheight=480;
constDWORDdesireddepth=16;
constintnMoveSpeed=100;
//设置动画速度为100毫秒/帧
constintnMoveIncX=8;
//设置子画面沿X轴移动8个像素
constintnMoveIncY=8;
//设置子画面沿y轴移动8个像素
BEGIN_MESSAGE_MAP(FlyWin,DirectDrawWin)
//{{AFX_MSG_MAP(FlyWin)
ON_WM_KEYDOWN()
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
FlyWin:
:
FlyWin()
x=nPreX=300;
//子画面初始位置为(300,150)
y=nPreY=150;
nIncX=nMoveIncX;
nIncY=nMoveIncY;
nCount=1;
//设置计数器
}
BOOLFlyWin:
CreateCustomSurfaces()
//createyoursurfaceshere...
//创建背景表面,并由指针bksurf指向这个表面
bksurf=CreateSurface(&
background.bmp&
);
//创建一个总子画面(由4帧子画面组成)的表面
//由指针flysurf指向这个表面.
flysurf=CreateSurface(&
bird.bmp&
//得到总子画面表面的宽(fw),高(fh)
GetSurfaceDimensions(flysurf,fw,fh);
//创建4帧宽为fw/2,高为fh/2的子画面的表面,分别由
//指针flysurf1,flysurf2,flysurf3,flysurf4指向它们。
//现在这4个子表面还是空的。
flysurf1=CreateSurface(fw/2,fh/2);
flysurf2=CreateSurface(fw/2,fh/2);
flysurf3=CreateSurface(fw/2,fh/2);
flysurf4=CreateSurface(fw/2,fh/2);
//清除4帧子画面表面的内容,使表面内所有像素为0,
//即表面是透明的。
ClearSurface(flysurf1,0);
ClearSurface(flysurf2,0);
ClearSurface(flysurf3,0);
ClearSurface(flysurf4,0);
//定义色彩键码,指明黑色(RGB=(0,0,0))为透明色
//即在blt操作期间不拷贝黑色像素。
ddck.dwColorSpaceLowValue=0;
ddck.dwColorSpaceHighValue=0;
//将色彩键码赋给背景表面,总子画面表面和4个子画面表面
bksurf&
flysurf&
flysurf1&
flysurf2&
flysurf3&
flysurf4&
//定义总子画面表面上的4个矩形区域,即为4个子画面表面区域
CRectr1(0,0,fw/2-1,fh/2-1);
CRectr2(fw/2,0,fw-1,fh/2-1);
CRectr3(0,fh/2,fw/2-1,fh-1);
CRectr4(fw/2,fh/2,fw-1,fh-1);
//把总子画面表面上的4个矩形区域分别拷贝到4个子画面表面
//即实现分离总子画面表面
SplitSurface(flysurf1,flysurf,r1,0,0);
SplitSurface(flysurf2,flysurf,r2,0,0);
SplitSurface(flysurf3,flysurf,r3,0,0);
SplitSurface(flysurf4,flysurf,r4,0,0);
//创建一个存储表面,由指针storesurf指向它
//用以存储子画面移动时所覆盖的背景区域
storesurf=CreateSurface(fw/2,fh/2);
CopySurface(storesurf,bksurf,x,y);
//初始化当前子画面表面
cursurf=flysurf1;
returnTRUE;
voidFlyWin:
DrawScene()
//绘制背景表面和第一帧子画面表面
//把背景表面拷贝到后备缓冲区
BltSurface(backsurf,bksurf,0,0,TRUE);
//把当前的子画面表面拷到后备缓冲区
BltSurface(backsurf,cursurf,x,y,TRUE);
//页面翻转,使后备缓冲区的内容可见
primsurf&
Flip(0,DDFLIP_WAIT);
//再次把背景表面拷贝到后备缓冲区
RestoreSurfaces()
//reclainlostsurfaceswiththeDirectDrawSurfaceRestore()function
//dependingonthesurface'
sfunction,itmaybenecessarytorestore
//surfacecontentaswell
if(bksurf&
IsLost())//如果bksurf
丢失
{
bksurf&
Restore();
//恢复内存
LoadSurface(bksurf,&
//恢复表面内容
}
if(flysurf&
IsLost())//如果flysurf丢失
flysurf&
LoadSurface(flysurf,&
intFlyWin:
SelectDriver()
intnumdrivers=GetNumDrivers();
if(numdrivers==1)
return0;
CArray
drivers;
for(inti=0;
i
{
LPSTRdesc,name;
GetDriverInfo(i,0,&desc,&name);
drivers.Add(desc);
DriverDialogdialog;
dialog.SetContents(&drivers);
if(dialog.DoModal()!
=IDOK)
return-1;
returndialog.GetSelection();
SelectInitialDisplayMode()
DWORDcurdepth=GetDisplayDepth();
inti,nummodes=GetNumDisplayModes();
DWORDw,h,d;
if(curdepth!
=desireddepth)
ddraw2&
SetDisplayMode(640,480,curdepth,0,0);
for(i=0;
GetDisplayModeDimensions(i,w,h,d);
if(w==desiredwidth&&h==desiredheight&&d==desireddepth)
returni;
if(d==desireddepth)
OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)
if(nChar==VK_ESCAPE)//按ESC退出
PostMessage(WM_CLOSE);
DirectDrawWin:
OnKeyDown(nChar,nRepCnt,nFlags);
OnCreate(LPCREATESTRUCTlpCreateStruct)
if(Direc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- DirectDraw 编写 动画 程序