BOOL FlyWin::CreateCustomSurfaces() { // create your surfaces here... //创建背景表面,并由指针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操作期间不拷贝黑色像素。 DDCOLORKEY ddck; ddck.dwColorSpaceLowValue=0; ddck.dwColorSpaceHighValue=0; //将色彩键码赋给背景表面,总子画面表面和4个子画面表面 bksurf→SetColorKey(DDCKEY_SRCBLT,&ddck); flysurf→SetColorKey(DDCKEY_SRCBLT,&ddck); flysurf1→SetColorKey(DDCKEY_SRCBLT,&ddck); flysurf2→SetColorKey(DDCKEY_SRCBLT,&ddck); flysurf3→SetColorKey(DDCKEY_SRCBLT,&ddck); flysurf4→SetColorKey(DDCKEY_SRCBLT,&ddck); //定义总子画面表面上的4个矩形区域,即为4个子画面表面区域 CRect r1(0,0,fw/2-1,fh/2-1); CRect r2(fw/2,0,fw-1,fh/2-1); CRect r3(0,fh/2,fw/2-1,fh-1); CRect r4(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; return TRUE; } void FlyWin::DrawScene() { //绘制背景表面和第一帧子画面表面 //把背景表面拷贝到后备缓冲区 BltSurface(backsurf,bksurf,0,0,TRUE); //把当前的子画面表面拷到后备缓冲区 BltSurface(backsurf,cursurf,x,y,TRUE); //页面翻转,使后备缓冲区的内容可见 primsurf→Flip(0,DDFLIP_WAIT); //再次把背景表面拷贝到后备缓冲区 BltSurface(backsurf,bksurf,0,0,TRUE); } void FlyWin::RestoreSurfaces() { // reclain lost surfaces with the DirectDrawSurface Restore() function // depending on the surface's function, it may be necessary to restore // surface content as well if(bksurf→IsLost()) //如果bksurf 丢失 { bksurf→Restore(); //恢复内存 LoadSurface(bksurf,“background.bmp”); //恢复表面内容 } if(flysurf→IsLost())//如果flysurf丢失 { flysurf→Restore(); //恢复内存 LoadSurface(flysurf,“bird.bmp”); //恢复表面内容 } } int FlyWin::SelectDriver() { int numdrivers=GetNumDrivers(); if (numdrivers==1) return 0; CArray drivers; for (int i=0;i { LPSTR desc, name; GetDriverInfo( i, 0, &desc, &name ); drivers.Add(desc); } DriverDialog dialog; dialog.SetContents( &drivers ); if (dialog.DoModal()!=IDOK) return -1; return dialog.GetSelection(); } int FlyWin::SelectInitialDisplayMode() { DWORD curdepth=GetDisplayDepth(); int i, nummodes=GetNumDisplayModes(); DWORD w,h,d; if (curdepth!=desireddepth) ddraw2→SetDisplayMode( 640, 480, curdepth, 0, 0 ); for (i=0;i { GetDisplayModeDimensions( i, w, h, d ); if (w==desiredwidth && h==desiredheight && d==desireddepth) return i; } for (i=0;i { GetDisplayModeDimensions( i, w, h, d ); if (d==desireddepth) return i; } return 0; } void FlyWin::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar==VK_ESCAPE) //按ESC退出 PostMessage( WM_CLOSE ); DirectDrawWin::OnKeyDown(nChar, nRepCnt, nFlags); } int FlyWin::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (DirectDrawWin::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here SetTimer(1,nMoveSpeed,NULL); //设置定时器 return 0; } void FlyWin::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default int nWhich=nCount%4+1; nCount++; //判断当前表面为4个子表面中的哪一个 switch(nWhich) { case 1: cursurf=flysurf1; break; case 2: cursurf=flysurf2; break; case 3: cursurf=flysurf3; break; case 4: cursurf=flysurf4; break; default: break; } //处理移动的子画面 x+=nIncX; y+=nIncY; //如子画面移动到屏幕下方或上方,应碰撞返回 if(y>=(int)(480-fh/2)||y<=0) { nIncY=-nIncY; y+=nIncY; } //如子画面移动到屏幕右方或左方,应碰撞返回 if(x>=(int)(640-fw/2)||x<=0) { nIncX=-nIncX; x+=nIncX; } //把当前表面拷贝到后备缓冲区 BltSurface(backsurf,cursurf,x,y,TRUE); //执行页面翻转,使后备缓冲区的内容可见 primsurf→Flip( 0, DDFLIP_WAIT ); //把备份的背景区域拷贝到后备缓冲区,以便恢复曾被 //覆盖的背景 BltSurface(backsurf,storesurf,nPreX,nPreY); //存储下一帧的子画面移动时所覆盖的背景区域于storesurf CopySurface(storesurf,bksurf,x,y); nPrex=x; nPrey=y; DirectDrawWin::OnTimer(nIDEvent); } void FlyWin::OnDestroy() { DirectDrawWin::OnDestroy(); // TODO: Add your message handler code here KillTimer(1); //取消定时器 } void FlyWin::CopySurface(LPDIRECTDRAWSURFACE ts, LPDIRECTDRAWSURFACE ss, int x,int y) { if(!ts || !ss ) return; DDSURFACEDESC tdesc,sdesc; //初始化sdesc,tdesc为零 ZeroMemory(&sdesc,sizeof(sdesc)); ZeroMemory(&tdesc,sizeof(tdesc)); sdesc.dwSize=sizeof(sdesc); tdesc.dwSize=sizeof(tdesc); //得到源表面ss,目标表面ts的描述信息 HRESULT r=ss→GetSurfaceDesc(&sdesc); if(r!=DD_OK) return; r=ts→GetSurfaceDesc(&tdesc); if(r!=DD_OK) return; //定义源表面上的矩形区域,大小大等于目标表面的面积 CRect rc(x,y,x+tdesc.dwWidth,y+tdesc.dwHeight); //超界处理 if(x+tdesc.dwWidth>(int)sdesc.dwWidth) return; if(y+tdesc.dwHeight>(int)sdesc.dwHeight) return; //拷贝源表面ss到目标表面ts r=ts→BltFast(0,0,ss,&rc, DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT); if(r!=DD_OK) return; } void FlyWin::SplitSurface(LPDIRECTDRAWSURFACE ts, LPDIRECTDRAWSURFACE ss, CRect& srcc, int x, int y) { if(!ts||!ss) return; DDSURFACEDESC tdesc,sdesc; ZeroMemory(&sdesc,sizeof(sdesc)); ZeroMemory(&tdesc,sizeof(tdesc)); sdesc.dwSize=sizeof(sdesc); tdesc.dwSize=sizeof(tdesc); HRESULT r=ts→GetSurfaceDesc(&tdesc); if(r!=DD_OK) return; r=ss→GetSurfaceDesc(&sdesc); if(r!=DD_OK) return; //超界处理 if(x+srcc.Width()>(int)tdesc.dwWidth) return; if(y+srcc.Height()>(int)tdesc.dwHeight) return; //把源表面srcc的矩形区域拷贝到目标表面左上角坐标为(x,y)处 r=ts→BltFast(x,y,ss,&srcc, DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT); if(r!=DD_OK) return; } DDSURFACEDESC为表面描述结构,用以保存表面的所有信息,它的成员变量dwSize为结构的大小而且必须要被初始化;dwHeight为表面的高度;dwWidth为表面的宽度。用函数GetSurfaceDesc()可以获取上述描述信息。 DirectDraw首先调用CreateCustomSurface()函数,我们将在这个函数中创建和准备程序所用到的表面。DrawSence()函数负责更新屏幕,因此我们用它来显示背景画面。我们主要的工作都在OnTimer()函数里,首先判断当前子画面为4帧子画面中的哪一帧,然后进行页面翻转、显示子画面和复制背景区域等操作。 BltFast()函数用于表面之间的拷贝,它的前两个参数指出blt的目标表面位置,第三个参数是指向源表面的指针,第四个参数是源表面上被拷贝的矩形区域,最后的参数是DDBLTFAST_SRCCOLORKEY和DDBLTFAST_WAIT,第一个标志用来激活源表面的色彩键码;第二个标志表示只有结束blt操作,BltFast()函数才返回。 Flip()函数用于页面翻转操作,使backsurf表面的内容可见。它有两个参数。第一个参数是个表面指针,它在用来翻转有多个后备缓冲区的表面时才有用;第二个参数是DDFLIP_WA IT标志,用来指示函数只有在表面完成之后才能返回。 当程序运行时,一个表面所在的内存可能会被另一个应用程序所占用,这形成了“表面丢失”。这时DirectDraw会调用RestoreSurface()函数来恢复丢失的表面。但是,如果你的显卡不是老掉牙了,这种情况一般是不会发生的。所以这里我只对两个主要表面bksurf、flysurf进行了恢复处理,而不再管其它的表面。 另外,函数SelectDriver()和SelectInitialDisplayMode()是AppWizard自动创建的。SelectDriver()选择一个显示驱动程序,SelectInitialDisplayMode()选择一个初始显示模式。 三、结束语 话已至此,你对DirectDraw编程应有一个大致的了解了吧!用DirectDraw编程其实很简单,说白了其实就是一句话:“几个表面之间拷来拷去”。只不过这其间可是大有文章可作的哟! 
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |