程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> DirectX帶控制的角色動畫(32位顯示模式)一

DirectX帶控制的角色動畫(32位顯示模式)一

編輯:關於C語言

。。真不容易啊,被個素材搞到我吐血,本來是8位的顯示模式,可是那效果太TMD的爛了,改了N小時,。。做了很多無用功
才改成32位模式。。那素材我糾結啊,1幀2幀掃描正常,3.4幀死活不能正常素描~,若有人知道是怎麼回事,麻煩告知一下。

 

就是這玩意,第一行 1 。2幀都掃描正常。之後的全部不正常


鍵盤方向鍵控制最下面的角色,由於只掃描了2幀動畫。看起來怪怪的- -。。我擦

 

  1. // INCLUDES ///////////////////////////////////////////////  
  2.  
  3. #define WIN32_LEAN_AND_MEAN  // just say no to MFC  
  4.  
  5. #define INITGUID  
  6.  
  7. #include <windows.h>   // include important windows stuff  
  8. #include <windowsx.h>   
  9. #include <mmsystem.h>  
  10. #include <iostream> // include important C/C++ stuff  
  11. #include <conio.h>  
  12. #include <stdlib.h>  
  13. #include <malloc.h>  
  14. #include <memory.h>  
  15. #include <string.h>  
  16. #include <stdarg.h>  
  17. #include <stdio.h>   
  18. #include <math.h>  
  19. #include <io.h>  
  20. #include <fcntl.h>  
  21.  
  22. #include <ddraw.h> // include directdraw  
  23.  
  24.  
  25. // DEFINES ////////////////////////////////////////////////  
  26.  
  27. // defines for windows   
  28. #define WINDOW_CLASS_NAME TEXT("WINCLASS1")  
  29.  
  30. // default screen size  
  31. #define SCREEN_WIDTH    640  // size of screen  
  32. #define SCREEN_HEIGHT   480  
  33. #define SCREEN_BPP      32 // bits per pixel  
  34.  
  35. #define BITMAP_ID            0x4D42 // universal id for a bitmap  
  36. #define MAX_COLORS_PALETTE   256  
  37. #define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))  
  38.  
  39. // TYPES //////////////////////////////////////////////////////  
  40.  
  41. // basic unsigned types  
  42. typedef unsigned short USHORT;  
  43. typedef unsigned short WORD;  
  44. typedef unsigned char  UCHAR;  
  45. typedef unsigned char  BYTE;  
  46.  
  47. //BMP 位圖容器 結構  
  48. typedef struct BITMAP_FILE_TAG  
  49. {  
  50.         BITMAPFILEHEADER bitmapfileheader;  // 包含位圖文件頭  
  51.         BITMAPINFOHEADER bitmapinfoheader;  // 位圖信息段,包含調色板如果有的話)  
  52.         PALETTEENTRY     palette[256];      // 調色板我們將存儲在這裡  
  53.         UCHAR            *buffer;           // 數據指針  
  54.  
  55. } BITMAP_FILE, *BITMAP_FILE_PTR;  
  56. typedef struct ALIEN_OBJ_TYP  
  57. {  
  58.         LPDIRECTDRAWSURFACE7 frames[2]; // 三幀的動畫完整步行周期  
  59.         int x,y;                        //外星人的位置  
  60.         int velocity;                   //X坐標的速度  
  61.         int current_frame;              // 當前幀的動畫  
  62.         int counter;                    // 動畫的使用時間  
  63.  
  64. } ALIEN_OBJ, *ALIEN_OBJ_PTR;  
  65. // PROTOTYPES  //////////////////////////////////////////////  
  66. //翻轉位圖  
  67. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);  
  68. //讀取位圖  
  69. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);  
  70. //釋放內存  
  71. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);  
  72. //生成離屏表面  
  73. LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width,int height,int mem_flags);  
  74. //生成剪輯器  
  75. LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,int num_rects,LPRECT clip_list);  
  76. //填充表面  
  77. int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color);  
  78. //掃描位圖  
  79. int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap,LPDIRECTDRAWSURFACE7 lpdds,int cx, int cy);      
  80. // MACROS /////////////////////////////////////////////////  
  81.  
  82.  
  83. #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)  
  84. #define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)  
  85.  
  86.  
  87. #define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }  
  88.  
  89. // GLOBALS ////////////////////////////////////////////////  
  90.  
  91. HWND      main_window_handle = NULL;   
  92. int       window_closed      = 0;      
  93. HINSTANCE hinstance_app      = NULL;   
  94.  
  95. // directdraw stuff  
  96.  
  97. LPDIRECTDRAW7         lpdd         = NULL;   // 申請接口對象  
  98. LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   //主表面  
  99. LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   //背面  
  100. LPDIRECTDRAWPALETTE   lpddpal      = NULL;   //調色板指針  
  101. LPDIRECTDRAWCLIPPER   lpddclipper  = NULL;   //剪切器  
  102. PALETTEENTRY          palette[256];          // 調色板  
  103. PALETTEENTRY          save_palette[256];     // 用於保存調色板  
  104. DDSURFACEDESC2        ddsd;                  // 直接繪制表面的描述結構  
  105. DDBLTFX               ddbltfx;               // 用來填充  
  106. DDSCAPS2              ddscaps;               //直接繪制表面的功能結構  
  107. HRESULT               ddrval;                // result back from dd calls  
  108. DWORD                 start_clock_count = 0; //用於定時  
  109.  
  110. BITMAP_FILE           bitmap;                // holds the bitmap  
  111.  
  112. ALIEN_OBJ             aliens[3];             //3個外星人  
  113.  
  114. LPDIRECTDRAWSURFACE7  lpddsbackground=NULL;        //這將保留背景圖片  
  115. char buffer[80];                             // general printing buffer  
  116. int gwidth  = -1;  
  117. int gheight = -1;  
  118.  
  119.  
  120.  
  121. // FUNCTIONS ////////////////////////////////////////////////  
  122.  
  123.  
  124.  
  125.  
  126.  
  127. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)  
  128. {  
  129.         //此函數打開一個位圖文件,並加載數據導入位圖  
  130.  
  131.         int file_handle,  // 文件句柄   
  132.                 index;        // 循環用的變量  
  133.  
  134.         UCHAR   *temp_buffer = NULL; //用於把24位轉換成16位的圖像  
  135.         OFSTRUCT file_data;          // 文件的數據信息  
  136.  
  137.         //打開文件,如果存在的話  
  138.         if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)  
  139.                 return(0);  
  140.  
  141.         // 現在載入位圖文件頭  
  142.         _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));  
  143.  
  144.         // 測試,如果這是一個位圖文件  
  145.         if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)  
  146.         {  
  147.                 // 關閉文件  
  148.                 _lclose(file_handle);  
  149.  
  150.                 // 返回 error  
  151.                 return(0);  
  152.         } // end if  
  153.  
  154.         //現在我們知道這是一個位圖,所以在讀取所有部分之前,  
  155.  
  156.         // 首先是讀取位圖的 infoheader  
  157.  
  158.         //現在載人位圖文件頭  
  159.         _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));  
  160.  
  161.  
  162.  
  163.         // 最後,讀取圖像數據本身  
  164.         _llseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);  
  165.  
  166.         //現在讀的圖像,如果圖像是8位或16位則僅僅是讀取它,  
  167.         //但如果是24位,就讀入一個臨時區域,然後將其轉換為16位的圖像  
  168.  
  169.         if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 ||   
  170.                 bitmap->bitmapinfoheader.biBitCount==24||bitmap->bitmapinfoheader.biBitCount==32)  
  171.         {  
  172.                 // 刪除最後的圖像,如果有的話  
  173.                 if (bitmap->buffer)  
  174.                         free(bitmap->buffer);  
  175.  
  176.                 // 為圖像分配內存  
  177.                 if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))  
  178.                 {  
  179.                         //分配失敗,關閉文件  
  180.                         _lclose(file_handle);  
  181.  
  182.                         // 返回 error  
  183.                         return(0);  
  184.                 } // end if  
  185.  
  186.                 // 現在讀取它  
  187.                 _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);  
  188.  
  189.         } // end if  
  190.         else 
  191.         {  
  192.                 // 出現嚴重問題  
  193.                 return(0);  
  194.  
  195.         } // end else  
  196.  
  197. #if 0  
  198.         // 寫出來的文件信息  
  199.         printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",  
  200.                 filename,  
  201.                 bitmap->bitmapinfoheader.biSizeImage,  
  202.                 bitmap->bitmapinfoheader.biWidth,  
  203.                 bitmap->bitmapinfoheader.biHeight,  
  204.                 bitmap->bitmapinfoheader.biBitCount,  
  205.                 bitmap->bitmapinfoheader.biClrUsed,  
  206.                 bitmap->bitmapinfoheader.biClrImportant);  
  207. #endif  
  208.  
  209.         // 關閉文件  
  210.         _lclose(file_handle);  
  211.  
  212.         // 翻轉位圖  
  213.         Flip_Bitmap(bitmap->buffer,   
  214.                 bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8),   
  215.                 bitmap->bitmapinfoheader.biHeight);  
  216.  
  217.  
  218.         return(1);  
  219.  
  220. } // end Load_Bitmap_File  
  221.  
  222. ///////////////////////////////////////////////////////////  
  223.  
  224. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)  
  225. {  
  226.         // 這個函數釋放與“位圖“相關聯的所有內存  
  227.         if (bitmap->buffer)  
  228.         {  
  229.                 // 釋放內存  
  230.                 free(bitmap->buffer);  
  231.  
  232.                 //指針置空  
  233.                 bitmap->buffer = NULL;  
  234.  
  235.         } // end if  
  236.  
  237.         // return success  
  238.         return(1);  
  239.  
  240. } // end Unload_Bitmap_File  
  241.  
  242. ///////////////////////////////////////////////////////////  
  243.  
  244. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)  
  245. {  
  246.         //此函數是用來翻轉自下而上的BMP圖像  
  247.  
  248.         UCHAR *buffer; //用來進行圖像處理  
  249.         int index;     //循環用的變量  
  250.  
  251.         //分配臨時緩沖區  
  252.         if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))  
  253.                 return(0);  
  254.  
  255.         // 將圖像復制到工作區  
  256.         memcpy(buffer,image,bytes_per_line*height);  
  257.  
  258.         // 垂直翻轉  
  259.         for (index=0; index < height; index++)  
  260.                 memcpy(&image[((height-1) - index)*bytes_per_line],  
  261.                 &buffer[index*bytes_per_line], bytes_per_line);  
  262.  
  263.         //釋放內存  
  264.         free(buffer);  
  265.  
  266.         // return success  
  267.         return(1);  
  268.  
  269. } // end Flip_Bitmap  
  270.  
  271. LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width,int height,  
  272.                                               int mem_flags)  
  273. {  
  274.                 //        這個函數創建一個簡單的離屏表面  
  275.         DDSURFACEDESC2 ddsd;  
  276.         LPDIRECTDRAWSURFACE7 lpdds;//臨時用的表面  
  277.  
  278.         //清空並設置size值  
  279.         DDRAW_INIT_STRUCT(ddsd);  
  280.         //設置寬,高,CAPS成員有效  
  281.         ddsd.dwFlags=DDSD_CAPS | DDSD_WIDTH|DDSD_HEIGHT;  
  282.         //設置離屏表面的尺寸  
  283.         ddsd.dwWidth=width;  
  284.         ddsd.dwHeight=height;  
  285.  
  286.         ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN |mem_flags;  
  287.  
  288.         //生成表面  
  289.         if (FAILED(lpdd->CreateSurface(&ddsd,&lpdds,NULL)))  
  290.         {  
  291.                 return 0;  
  292.         }  
  293.         //設置色彩鍵  
  294.         DDCOLORKEY color_key;  
  295.         color_key.dwColorSpaceLowValue=0;  
  296.         color_key.dwColorSpaceHighValue=0;  
  297.  
  298.         //設置綁定  
  299.         lpdds->SetColorKey(DDCKEY_SRCBLT,&color_key);  
  300.         return lpdds;  
  301. }  
  302.           
  303.  
  304. LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,  
  305.         int num_rects,  
  306.         LPRECT clip_list)  
  307.  
  308. {  
  309.         //這個函數創建一個從發送剪輯列表Clipper和其附加到發送的表面  
  310.  
  311.         int index;                         // 循環變量  
  312.         LPDIRECTDRAWCLIPPER lpddclipper;   // 創建一個指向剪切器的指針  
  313.         LPRGNDATA region_data;             // 數據指針  
  314.         // the header and clip list  
  315.  
  316.         // 創建剪切器  
  317.         if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))  
  318.                 return(NULL);  
  319.  
  320.         //現在創建剪輯列表發送的數據  
  321.  
  322.         //第一個區域的數據存儲器分配  
  323.         region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));  
  324.  
  325.         // 現在復制到該矩形的區域的數據  
  326.         memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);  
  327.  
  328.         // set up fields of header  
  329.         region_data->rdh.dwSize          = sizeof(RGNDATAHEADER);  
  330.         region_data->rdh.iType           = RDH_RECTANGLES;  
  331.         region_data->rdh.nCount          = num_rects;  
  332.         region_data->rdh.nRgnSize        = num_rects*sizeof(RECT);  
  333.  
  334.         region_data->rdh.rcBound.left    =  64000;  
  335.         region_data->rdh.rcBound.top     =  64000;  
  336.         region_data->rdh.rcBound.right   = -64000;  
  337.         region_data->rdh.rcBound.bottom  = -64000;  
  338.  
  339.         // find bounds of all clipping regions  
  340.         for (index=0; index<num_rects; index++)  
  341.         {  
  342.                 // test if the next rectangle unioned with the current bound is larger  
  343.                 if (clip_list[index].left < region_data->rdh.rcBound.left)  
  344.                         region_data->rdh.rcBound.left = clip_list[index].left;  
  345.  
  346.                 if (clip_list[index].right > region_data->rdh.rcBound.right)  
  347.                         region_data->rdh.rcBound.right = clip_list[index].right;  
  348.  
  349.                 if (clip_list[index].top < region_data->rdh.rcBound.top)  
  350.                         region_data->rdh.rcBound.top = clip_list[index].top;  
  351.  
  352.                 if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)  
  353.                         region_data->rdh.rcBound.bottom = clip_list[index].bottom;  
  354.  
  355.         } // end for index  
  356.  
  357.         // now we have computed the bounding rectangle region and set up the data  
  358.         // now let's set the clipping list  
  359.  
  360.         if (FAILED(lpddclipper->SetClipList(region_data, 0)))  
  361.         {  
  362.                 // release memory and return error  
  363.                 free(region_data);  
  364.                 return(NULL);  
  365.         } // end if  
  366.  
  367.         // now attach the clipper to the surface  
  368.         if (FAILED(lpdds->SetClipper(lpddclipper)))  
  369.         {  
  370.                 // release memory and return error  
  371.                 free(region_data);  
  372.                 return(NULL);  
  373.         } // end if  
  374.  
  375.         // all is well, so release memory and send back the pointer to the new clipper  
  376.         free(region_data);  
  377.         return(lpddclipper);  
  378.  
  379. } // end DDraw_Attach_Clipper  
  380.  
  381. int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color)  
  382. {  
  383.         DDBLTFX ddbltfx;   
  384.  
  385.         // 清空並設置size字段  
  386.         DDRAW_INIT_STRUCT(ddbltfx);  
  387.  
  388.         // 設置填充顏色  
  389.         ddbltfx.dwFillColor = color;   
  390.  
  391.         // 准備blt到表面  
  392.         lpdds->Blt(NULL,       // ptr to dest rectangle  
  393.                 NULL,       // ptr to source surface, NA              
  394.                 NULL,       // ptr to source rectangle, NA  
  395.                 DDBLT_COLORFILL | DDBLT_WAIT,   // fill and wait                     
  396.                 &ddbltfx);  // ptr to DDBLTFX structure  
  397.  
  398.         // return success  
  399.         return(1);  
  400. } // end DDraw_Fill_Surface  
  401.  
  402. ///////////////////////////////////////////////////////////////  
  403.  
  404. int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7 source, // 要畫的源表面  
  405.         int x, int y,                 // 要繪制的位置  
  406.         int width, int height,        // 源表面的尺寸  
  407.         LPDIRECTDRAWSURFACE7 dest,    // 要畫的目標表面  
  408.         int transparent = 1)          //透明顏色標志  
  409. {  
  410.         // draw a bob at the x,y defined in the BOB  
  411.         // on the destination surface defined in dest  
  412.  
  413.         RECT dest_rect,   //目標矩形  
  414.                 source_rect; // 源矩形                               
  415.  
  416.         //設置目標矩形的數據  
  417.         dest_rect.left   = x;  
  418.         dest_rect.top    = y;  
  419.         dest_rect.right  = x+width-1;  
  420.         dest_rect.bottom = y+height-1;  
  421.  
  422.         //設置源矩形的數據  
  423.         source_rect.left    = 0;  
  424.         source_rect.top     = 0;  
  425.         source_rect.right   = width-1;  
  426.         source_rect.bottom  = height-1;  
  427.  
  428.         // 透明度標志測試  
  429.  
  430.         if (transparent)  
  431.         {  
  432.                 //啟用色彩鍵  
  433.                   if (FAILED(dest->Blt(&dest_rect, source,  
  434.                         &source_rect,(DDBLT_WAIT | DDBLT_KEYSRC),  
  435.                         NULL)))  
  436.                         return(0);  
  437.  
  438.         } // end if  
  439.         else 
  440.         {  
  441.                 //不啟用色彩鍵  
  442.                 if (FAILED(dest->Blt(&dest_rect, source,  
  443.                         &source_rect,(DDBLT_WAIT),  
  444.                         NULL)))  
  445.                         return(0);  
  446.  
  447.         } // end if  
  448.  
  449.         // return success  
  450.         return(1);  
  451.  
  452. } // end DDraw_Draw_Surface  
  453.  
  454. int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap,     // 存放要掃描的位圖文件的數據  
  455.         LPDIRECTDRAWSURFACE7 lpdds, // 在表面存儲數據  
  456.         int cx, int cy)             // 掃描圖像的單元  
  457. {  
  458.         //此函數從位圖文件中提取數據  
  459.  
  460.         UCHAR *source_ptr;   // working pointers  
  461.         DWORD        *dest_ptr;  
  462.  
  463.         DDSURFACEDESC2 ddsd;  //  直接繪制表面的描述  
  464.  
  465.         //獲取到目標表面的內存地址  
  466.    //設置結構的大小  
  467.         ddsd.dwSize = sizeof(ddsd);  
  468.  
  469.         // 鎖定表面  
  470.         lpdds->Lock(NULL,  
  471.                 &ddsd,  
  472.                 DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,  
  473.                 NULL);  
  474.         int ccx,ccy;  
  475.         // 計算開始掃描的位置  
  476.         cx = cx*(ddsd.dwWidth) ;  
  477.         cy = cy*(ddsd.dwHeight) ;  
  478.  
  479.         gwidth  = ddsd.dwWidth;  
  480.         gheight = ddsd.dwHeight;  
  481.  
  482.  
  483.  
  484.  
  485.         // extract bitmap data  
  486.         source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;  
  487.  
  488.         // assign a pointer to the memory surface for manipulation  
  489.         dest_ptr = (DWORD *)ddsd.lpSurface;  
  490.  
  491.         // iterate thru each scanline and copy bitmap  
  492.         for (int index_y = 0; index_y < 80; index_y++)  
  493.         {  
  494.                 for (int index_x = cx; index_x <cx+gwidth; index_x++)  
  495.                 {  
  496.                         // get BGR values  
  497.                         UCHAR blue  = (bitmap->buffer[index_y*640*4 + index_x*4 + 0]),  
  498.                                   green = (bitmap->buffer[index_y*640*4 + index_x*4 + 1]),  
  499.                                   red   = (bitmap->buffer[index_y*640*4 + index_x*4 + 2]);  
  500.  
  501.                         // this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)  
  502.                         DWORD pixel = _RGB32BIT(0,red,green,blue);  
  503.  
  504.                         // write the pixel  
  505.                         dest_ptr[index_x + (index_y*ddsd.lPitch >> 2)] = pixel;  
  506.  
  507.                 } // end for index_x  
  508.  
  509.         } // end for index_y  
  510.  
  511.         // unlock the surface   
  512.         lpdds->Unlock(NULL);  
  513.  
  514.         // return success  
  515.         return(1);  
  516.  
  517. } // end Scan_Image_Bitmap  
  518.  

還有後面一部分,放在第二個文章裡

本文出自 “Chaos代碼空間” 博客,請務必保留此出處http://flzt5354.blog.51cto.com/1568074/589804

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved