My_DirectDraw.cpp
上传用户:may_xy
上传日期:2007-08-09
资源大小:1519k
文件大小:14k
源码类别:

游戏

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "MainFrm.h"
  3. #include "Game.h"
  4. #include "My_DirectInput.h"
  5. #include "my_directdraw.h"
  6. #include "Draw_Cards_Engine.h"
  7. #include "Playing_Cards.h"
  8. #include <io.h>
  9. CMyDirectDraw::CMyDirectDraw()
  10. {
  11. lpdd         = NULL;   // dd object
  12. lpddclipper  = NULL;   // dd clipper
  13. bitmap.buffer = NULL; //记住!!!!!!初始化!!!!!永远的伤
  14. start_clock_count = 0; // used for timing
  15. SCREEN_BPP = 32;
  16. }
  17. int CMyDirectDraw::Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
  18. {
  19. // 将数据读入表面
  20. UCHAR *buffer; // used to perform the image processing
  21. int index;  
  22. if (!(buffer = (UCHAR *)new UCHAR[bytes_per_line*height]) )
  23. return(0);
  24. memcpy(buffer,image,bytes_per_line*height);
  25. for (index=0; index < height; index++)
  26. {
  27.     memcpy(&image[((height-1) - index)*bytes_per_line],
  28.    &buffer[index*bytes_per_line], bytes_per_line);
  29. }
  30. // release the memory
  31. delete(buffer);
  32. return(1);
  33. } // end Flip_Bitmap
  34. //读取位图的方法:
  35. int CMyDirectDraw::Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
  36. {
  37. //
  38. int file_handle;  // the file handle
  39.        
  40. UCHAR   *temp_buffer = NULL; 
  41. OFSTRUCT file_data;     
  42. // 打开文件如果它存在;
  43. if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
  44.    return(0);
  45. _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
  46. if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
  47. {
  48. //如果不是位图,则关闭文件,返回;
  49.   _lclose(file_handle);
  50.   return(0);
  51.     } // end if
  52. // 发现是位图,继续;
  53. // 读取文件头;
  54. _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
  55. //如果是8位位图,则返回;
  56. if (bitmap->bitmapinfoheader.biBitCount == 8)
  57. {
  58. AfxMessageBox("本游戏不能读取8位位图!");
  59. return 0;
  60. } // end if
  61. //从文件结尾反向搜位图数据字节大小的长度;
  62. _lseek(file_handle,(int)(sizeof(BITMAPFILEHEADER)+
  63.    sizeof(BITMAPINFOHEADER)),SEEK_SET);
  64. int Image_Size = bitmap->bitmapfileheader.bfSize-
  65. (sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));
  66. if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 || 
  67.     bitmap->bitmapinfoheader.biBitCount==24)
  68.     {
  69. //如果位图存在,则先释放;
  70.    if (bitmap->buffer)
  71.        free(bitmap->buffer);
  72.    if ( !(bitmap->buffer = (UCHAR *)new UCHAR [Image_Size]) )
  73.       {
  74.  
  75. _lclose(file_handle);
  76. return(0);
  77.       } 
  78.    _lread(file_handle,bitmap->buffer,Image_Size);
  79. else
  80. {
  81.    //见鬼了!
  82.    return(0);
  83.     } 
  84. _lclose(file_handle);
  85. // flip the bitmap
  86. Flip_Bitmap(bitmap->buffer, 
  87.             bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
  88.             bitmap->bitmapinfoheader.biHeight);
  89. return(1);
  90. int CMyDirectDraw::Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
  91. {
  92. // this function releases all memory associated with "bitmap"
  93. if (bitmap->buffer)
  94. {
  95.    // release memory
  96.    delete(bitmap->buffer);
  97.    bitmap->buffer = NULL;
  98.     } 
  99. return(1);
  100. int CMyDirectDraw::Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap,     // bitmap file to scan image data from
  101.                       LPDIRECTDRAWSURFACE7 lpdds, // surface to hold data
  102.                       int cx, int cy)             // cell to scan image from
  103. {
  104. //将位图像素写到表面去!
  105. DDSURFACEDESC2 ddsd;  //  direct draw surface description 
  106.  
  107. // set size of the structure
  108. ddsd.dwSize = sizeof(ddsd);
  109. // lock the display surface
  110. lpdds->Lock(NULL,
  111.             &ddsd,
  112.             DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
  113.             NULL);
  114. cx = cx*(ddsd.dwWidth+1) + 1;
  115. cy = cy*(ddsd.dwHeight+1) + 1;
  116. DWORD *dest_ptr;
  117. UCHAR blue,green,red;
  118. dest_ptr = (DWORD *)ddsd.lpSurface;
  119. for (DWORD index_y = 0; index_y < ddsd.dwHeight; index_y++)
  120. {
  121. for (DWORD index_x = 0; index_x < ddsd.dwWidth; index_x++)
  122. {
  123.         // get BGR values;;;;
  124. int index = index_y*(bitmap->bitmapinfoheader.biWidth)*3 + index_x*3;
  125. blue  = bitmap->buffer[index + 0];
  126. green = bitmap->buffer[index + 1];
  127. red   = bitmap->buffer[index + 2];
  128.         // 32位RGB数;
  129. DWORD pixel = _RGB32BIT(0,red,green,blue);
  130. dest_ptr[index_x + (index_y*ddsd.lPitch >> 2)] = pixel;
  131. // unlock the surface 
  132. lpdds->Unlock(NULL);
  133. return(1);
  134. }
  135. //填充表面的方法
  136. int CMyDirectDraw::FillSurface(LPDIRECTDRAWSURFACE7 lpdds,int color)
  137. {
  138. DDBLTFX ddbltfx;
  139. //初始化ddbltfx结构;
  140. DDRAW_INIT_STRUCT(ddbltfx);
  141. // 需要填空全屏的颜色值;
  142. ddbltfx.dwFillColor = color; 
  143. // blt to surface
  144. lpdds->Blt(
  145.    NULL,       // ptr to dest rectangle
  146.            NULL,       // ptr to source surface, NA            
  147.            NULL,       // ptr to source rectangle, NA
  148.            DDBLT_COLORFILL | DDBLT_WAIT,   // fill and wait                   
  149.        &ddbltfx
  150.    );  // ptr to DDBLTFX structure
  151. return(1);
  152. } // end FillSurface
  153. //根据传入参数建立相应的表面
  154. LPDIRECTDRAWSURFACE7 CMyDirectDraw::CreateSurface(
  155.   int width,
  156.   int height,
  157.   int mem_flags,
  158.   int color = 0)
  159. {
  160. // this function creates an offscreen plain surface
  161. DDSURFACEDESC2 ddsd;         // working description
  162. LPDIRECTDRAWSURFACE7 lpdds;  // temporary surface
  163.     
  164. // set to access caps, width, and height
  165. memset(&ddsd,0,sizeof(ddsd));
  166. ddsd.dwSize  = sizeof(ddsd);
  167. ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  168. // set dimensions of the new bitmap surface
  169. ddsd.dwWidth  =  width;
  170. ddsd.dwHeight =  height;
  171. // set surface to offscreen plain
  172. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;
  173. // create the surface
  174. if (FAILED(lpdd->CreateSurface(&ddsd,&lpdds,NULL)))
  175.    return(NULL);
  176. // test if user wants a color key
  177. if (color >= 0)
  178.     {
  179.    // set color key to color 0
  180.    DDCOLORKEY color_key; // used to set color key
  181.    color_key.dwColorSpaceLowValue  = color;
  182.    color_key.dwColorSpaceHighValue = color;
  183.    // now set the color key for source blitting
  184.    lpdds->SetColorKey(DDCKEY_SRCBLT, &color_key);
  185. }  // end if
  186. // return surface
  187. return(lpdds);
  188. } // end CreateSurface
  189. int CMyDirectDraw::DrawSurface(
  190.   LPDIRECTDRAWSURFACE7 source, // source surface to draw
  191.                       int x, int y,                 // position to draw at
  192.                       int width, int height,        // size of source surface
  193.                       LPDIRECTDRAWSURFACE7 dest,    // surface to draw the surface on
  194.                       int transparent = 1)          // transparency flag
  195. {
  196. // draw a bob at the x,y defined in the BOB
  197. // on the destination surface defined in dest
  198. RECT dest_rect,   // the destination rectangle
  199.  source_rect; // the source rectangle                             
  200. // fill in the destination rect
  201. dest_rect.left   = x;
  202. dest_rect.top    = y;
  203. dest_rect.right  = x+width;
  204. dest_rect.bottom = y+height;
  205. // fill in the source rect
  206. source_rect.left    = 0;
  207. source_rect.top     = 0;
  208. source_rect.right   = width;
  209. source_rect.bottom  = height;
  210. // test transparency flag
  211. if (transparent)
  212.     {
  213.    // enable color key blit
  214.    // blt to destination surface
  215.    if (FAILED(dest->Blt(&dest_rect, source,
  216.                      &source_rect,(DDBLT_WAIT | DDBLT_KEYSRC),
  217.                      NULL)))
  218.             return(0);
  219. } // end if
  220. else
  221.     {
  222.    // perform blit without color key
  223.    // blt to destination surface
  224. if (FAILED(dest->Blt(&dest_rect, source,
  225.                      &source_rect,(DDBLT_WAIT),
  226.                      NULL)))
  227.            return(0);
  228. } // end if
  229. // return success
  230. return(1);
  231. } // end DrawSurface
  232. //创建剪切的方法:
  233. LPDIRECTDRAWCLIPPER CMyDirectDraw::AttachClipper(
  234.  LPDIRECTDRAWSURFACE7 lpdds,
  235.                                          int num_rects,
  236.                                          LPRECT clip_list)
  237. {
  238. // this function creates a clipper from the sent clip list and attaches
  239. // it to the sent surface
  240. int index;                         // looping var
  241. LPDIRECTDRAWCLIPPER lpddclipper;   // pointer to the newly created dd clipper
  242. LPRGNDATA region_data;             // pointer to the region data that contains
  243.                                    // the header and clip list
  244. // first create the direct draw clipper
  245. if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))
  246.    return(NULL);
  247. // now create the clip list from the sent data
  248. // first allocate memory for region data
  249. region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));
  250. // now copy the rects into region data
  251. memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);
  252. // set up fields of header
  253. region_data->rdh.dwSize          = sizeof(RGNDATAHEADER);
  254. region_data->rdh.iType           = RDH_RECTANGLES;
  255. region_data->rdh.nCount          = num_rects;
  256. region_data->rdh.nRgnSize        = num_rects*sizeof(RECT);
  257. region_data->rdh.rcBound.left    =  64000;
  258. region_data->rdh.rcBound.top     =  64000;
  259. region_data->rdh.rcBound.right   = -64000;
  260. region_data->rdh.rcBound.bottom  = -64000;
  261. // find bounds of all clipping regions
  262. for (index=0; index<num_rects; index++)
  263.     {
  264.     // test if the next rectangle unioned with the current bound is larger
  265.     if (clip_list[index].left < region_data->rdh.rcBound.left)
  266.         region_data->rdh.rcBound.left = clip_list[index].left;
  267.     if (clip_list[index].right > region_data->rdh.rcBound.right)
  268.         region_data->rdh.rcBound.right = clip_list[index].right;
  269.     if (clip_list[index].top < region_data->rdh.rcBound.top)
  270.         region_data->rdh.rcBound.top = clip_list[index].top;
  271.     if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)
  272.         region_data->rdh.rcBound.bottom = clip_list[index].bottom;
  273.     } // end for index
  274. // now we have computed the bounding rectangle region and set up the data
  275. // now let's set the clipping list
  276. if (FAILED(lpddclipper->SetClipList(region_data, 0)))
  277.     {
  278.    // release memory and return error
  279. free(region_data);
  280. return(NULL);
  281. } // end if
  282. // now attach the clipper to the surface
  283. if (FAILED(lpdds->SetClipper(lpddclipper)))
  284.     {
  285.    // release memory and return error
  286.    free(region_data);
  287.    return(NULL);
  288. } // end if
  289. // all is well, so release memory and send back the pointer to the new clipper
  290. free(region_data);
  291. return(lpddclipper);
  292. //调试用;
  293. int CMyDirectDraw::DebugText(char* text,int time)
  294. {
  295. HDC xdc; // the working dc
  296. if (FAILED(lpddsprimary->GetDC(&xdc)))
  297.    return(0);
  298. SetBkMode(xdc, TRANSPARENT);
  299. TextOut(xdc,140,500,text,strlen(text));
  300. lpddsprimary->ReleaseDC(xdc);
  301. ::Sleep(time);
  302. return 1;
  303. }
  304. int CMyDirectDraw::TextGDI(
  305. char *text,
  306. int x,
  307. int y,
  308. COLORREF color,
  309. int size,
  310. char* type,
  311. LPDIRECTDRAWSURFACE7 lpdds)
  312. {
  313. HDC xdc; 
  314. if (FAILED(lpdds->GetDC(&xdc)))
  315.    return(0);
  316. LOGFONT my_font;
  317. memset(&my_font,0,sizeof(LOGFONT));
  318. my_font.lfCharSet = DEFAULT_CHARSET;
  319. my_font.lfHeight = size;
  320. // lstrcpyn(my_font.lfFaceName, type, _countof(my_font.lfFaceName));
  321. sprintf(my_font.lfFaceName,type);
  322. POINT pt;
  323. pt.y = ::GetDeviceCaps(xdc, LOGPIXELSY) * my_font.lfHeight;
  324. pt.y /= 720;    // 72 points/inch, 10 decipoints/point
  325. ::DPtoLP(xdc, &pt, 1);
  326. POINT ptOrg = { 0, 0 };
  327. ::DPtoLP(xdc, &ptOrg, 1);
  328. my_font.lfHeight = -abs(pt.y - ptOrg.y);
  329. HFONT hFont;
  330. hFont = ::CreateFontIndirect(&my_font);
  331. // dc.m_hDC  = xdc;
  332. //新字体对象及指针;
  333. // CFont my_font;
  334. //把新建字体选进描述中;
  335. // my_font.CreatePointFont(size,type,NULL);//创建自己的字体;
  336. // old_font = dc.SelectObject(&my_font);  //选择新的字体;
  337. SelectObject(xdc,hFont);
  338. SetTextColor(xdc,color);
  339. SetBkMode(xdc,TRANSPARENT);
  340. TextOut(xdc,x,y,text,strlen(text));
  341. //恢复原设备描述符表的字体;
  342. DeleteObject(hFont);
  343. lpdds->ReleaseDC(xdc);
  344. return 1;
  345. }
  346. //初始化DD平台;
  347. int CMyDirectDraw::Init()
  348. {
  349. // pCMainFrame = *)AfxGetMainWnd();
  350. if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
  351. {
  352.    return(0);
  353. }
  354. // set cooperation to full screen
  355. if(FAILED(lpdd->SetCooperativeLevel(::pCMainFrame->m_hWnd, 
  356.  DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN |
  357.                                      DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)) )  // 
  358. {
  359.    return(0);
  360. }
  361. if (FAILED(lpdd->SetDisplayMode(Screen_Width, Screen_Height, SCREEN_BPP,0,0)))
  362. {
  363.    return(0);
  364. }
  365. DDRAW_INIT_STRUCT(ddsd);  //清零的宏;
  366. // enable valid fields
  367. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  368. // set the backbuffer count field to 1, use 2 for triple buffering
  369. ddsd.dwBackBufferCount = 1;
  370. // request a complex, flippable
  371. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
  372. // 创建主表面;
  373. if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
  374. return(0);
  375. ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  376. if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
  377.   return(0);
  378. //设置后备缓冲区的剪裁区;
  379. RECT screen_rect= {0,0,Screen_Width,Screen_Height};
  380. lpddclipper = AttachClipper(lpddsback,1,&screen_rect);
  381. return 1;
  382. int CMyDirectDraw::BitmapToSurface(
  383. LPDIRECTDRAWSURFACE7 Dest_Surface,  //目的表面;
  384. int Dest_x, //目的表面x座标;
  385. int Dest_y, //目的表面y座标;
  386. char* filename, //源位图文件名;
  387. int Bitmap_Width, //位图宽;
  388. int Bitmap_Height //位图长;
  389. )
  390. {
  391. HBITMAP hbitmap;
  392. HDC hdc;   //接受当前设备环境句柄;
  393. HDC dhdc;
  394. CString str;
  395. hdc = ::CreateCompatibleDC(NULL);
  396. hbitmap = (HBITMAP)::LoadImage(NULL,filename,IMAGE_BITMAP,Bitmap_Width,Bitmap_Height,LR_LOADFROMFILE); 
  397. if(hbitmap==NULL)
  398. {
  399. str.Format("无法载入位图%s",filename);
  400. AfxMessageBox(str);
  401. return 0;
  402. }
  403. ::SelectObject(hdc,hbitmap);
  404. Dest_Surface->GetDC( &dhdc );
  405. ::BitBlt( dhdc , Dest_x , Dest_y ,Bitmap_Width,Bitmap_Height, hdc , 0 , 0 , SRCCOPY );
  406. Dest_Surface->ReleaseDC(dhdc);
  407. return 1;
  408. }
  409. CMyDirectDraw::~CMyDirectDraw()
  410. {
  411. // now the primary surface
  412. // if (lpddsprimary)
  413.  //   {
  414. // lpddsprimary->Release();
  415. // lpddsprimary = NULL;
  416. // } // end if
  417. //后备缓冲
  418. // if(lpddsback)
  419. // {
  420. // lpddsback->Release();
  421. // lpddsback = NULL;
  422. // }
  423. //离屏表面;
  424. // if(lpddsbackground)
  425. // {
  426. // lpddsbackground->Release();
  427. // lpddsbackground = NULL;
  428. // }
  429. // now blow away the IDirectDraw4 interface
  430. if (lpdd)
  431.     {
  432. lpdd->Release();
  433. lpdd = NULL;
  434.     } // end if