<Win32_3>Bitmap位图应用2 ------ 键盘控制人物走动

今天掌握了Bitmap的用法,忍不住再来一次升级版的应用------用键盘控制人物的走动,这个可能在游戏设计中用的很多,不过今儿就先来小试牛刀,呵呵……

 

本人学习编程有个"癖好"  —— 那就是有了想法,下一步就是实现,越快实现越好,不实现就誓不罢休……

 

好了,F话少说了,还是先来逐步了解需求吧

(1)首先需要一个完整的人物走路分解图,每一个方向4张,分别是:直立、右脚向前、直立、左脚向前

(资源由本人亲自制作,待会儿上传^_^)

(2)加载位图到内存中,这个和Bitmap应用1一样,不再赘述

(3)获取位图ID

首先需要写两个方法:

  1. IDB_BITMAP GetBitmapID(int dir, int dirCount);                  //获取当前绘制的位图ID  
  2. void DrawBitmap(HINSTANCEHDCintintintint);    //绘制位图  
  3. (IDB_BITMAP就是int)  

 

本程序总共需要16张位图,位图ID是从101开始,每一张是紧挨着的(101~116),所以可以通过ID这个特点来控制位图的选择

GetBitmapID()的参数dir取以下4个之1:(位图的排列顺序为: 前后左右)

  1. //位图的方位  
  2. #define DIR_FRONT   0  
  3. #define DIR_REAR    1  
  4. #define DIR_LEFT    2  
  5. #define DIR_RIGHT   3  

参数dirCount取以下4个之1(也就是方向键连续按下的次数,每次对4求余数,因为每一个方向有4张分解图)

  1. static int      frontC, rearC, leftC, rightC;  
  2. //计数是为了控制每个方向所显示状态(立正、右脚向前、立正、左脚向前)  

然后简单的运算就能得到相应的位图ID号:

101 + dir*4 + dirCount

 

(4)用键盘控制人物的走动

由于每一个方向的处理类似,这里就简述一下向前走的控制算法:

  1. rearC=leftC=rightC=0;//清除  
  2.   
  3. //控制移动的距离  
  4. if(!(frontC % 2))   //当人物直立时,移动距离控制为10  
  5. {  
  6.     y += 10;  
  7. }         
  8. else        //当人物左脚或右脚向前时,移动距离控制为2   这是经过多次测试得到的数据,这样控制的效果较好  
  9. {  
  10.     y += 2;  
  11. }  
  12.   
  13. DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y);//绘制人物的状态  
  14. frontC = (frontC+1) % 4;//计算本方向(如果继续按下Dowm键)的下一次移动  

 

(5)清除上一步的状态,也就是将上一步的位图刷掉

方法还是调用BitBlt()方法,只不过是绘制一块白色的位图,仅仅需要将最后一个参数设定为WHITENESS就ok了

 

好了这就是全过程,以下就是完整代码:

  1. //前后左右移动的小猫  
  2. #include<windows.h>  
  3. #include<stdio.h>  
  4. #include"resource.h"  
  5.   
  6. //位图的方位  
  7. #define DIR_FRONT   0  
  8. #define DIR_REAR    1  
  9. #define DIR_LEFT    2  
  10. #define DIR_RIGHT   3  
  11.   
  12. //类型的重定义  
  13. typedef int         IDB_BITMAP;  
  14.   
  15. /**    为重绘保存上一步的信息    **/  
  16. //保存上一步的位图  
  17. BITMAP  lastBitmap;  
  18. //保存上一步位图的坐标  
  19. int     lastX, lastY;  
  20. //保存上一步位图的方向和按键计数  
  21. int     lastDir, lastDirCount;  
  22.   
  23. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);  
  24. IDB_BITMAP GetBitmapID(intint);                       //获取当前绘制的位图ID  
  25. void DrawBitmap(HINSTANCEHDCintintintint);    //绘制位图  
  26.   
  27. int WINAPI WinMain(HINSTANCE hInstance,  
  28.                    HINSTANCE hPrevInstance,  
  29.                    PSTR szCmdLine,  
  30.                    int iCmdShow)  
  31. {  
  32.     static  TCHAR   szAppName[] = TEXT("MoveCat");  
  33.     HWND            hwnd;  
  34.     MSG             msg;  
  35.     WNDCLASS        wndclass;  
  36.       
  37.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
  38.     wndclass.lpfnWndProc    = WndProc;  
  39.     wndclass.cbClsExtra     = 0;  
  40.     wndclass.cbWndExtra     = 0;  
  41.     wndclass.hInstance      = hInstance;  
  42.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
  43.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  44.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  45.     wndclass.lpszMenuName   = NULL;  
  46.     wndclass.lpszClassName  = szAppName;  
  47.       
  48.     if(!RegisterClass(&wndclass))  
  49.     {  
  50.         MessageBox(NULL, TEXT("This program requires Windows NT!"),  
  51.             szAppName, MB_ICONERROR);  
  52.         return 0;  
  53.     }  
  54.       
  55.     hwnd = CreateWindow(szAppName,  
  56.                         TEXT("MoveCat Demo"),  
  57.                         WS_OVERLAPPEDWINDOW,  
  58.                         (1366 - 720) / 2,  
  59.                         (768 - 570) / 2,  
  60.                         720,  
  61.                         570,  
  62.                         NULL,  
  63.                         NULL,  
  64.                         hInstance,  
  65.                         NULL);  
  66.   
  67.     ShowWindow(hwnd, iCmdShow);  
  68.     UpdateWindow(hwnd);  
  69.   
  70.     while(GetMessage(&msg, NULL, 0, 0))  
  71.     {  
  72.         TranslateMessage(&msg);  
  73.         DispatchMessage(&msg);  
  74.     }  
  75.       
  76.     return msg.wParam;  
  77. }  
  78.   
  79. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  80. {  
  81.     static HINSTANCE    hInstance;//窗口的实例句柄  
  82.     static int          frontC, rearC, leftC, rightC, x, y;  
  83.     //分别表示方位键按键计数和位图显示的位置  计数是为了控制每个方向所显示状态(立正、右脚向前、立正、左脚向前)  
  84.     HDC                 hdc;  
  85.     PAINTSTRUCT         ps;  
  86.       
  87.     switch(message)  
  88.     {  
  89.     case WM_CREATE:  
  90.         hInstance = ((LPCREATESTRUCT)lParam)->hInstance;  
  91.         return 0 ;  
  92.   
  93.     case WM_PAINT:  
  94.         hdc = BeginPaint(hwnd, &ps);  
  95.   
  96.         if(lastBitmap.bmWidth)  
  97.         {  
  98.             DrawBitmap(hInstance, hdc, lastDir, lastDirCount, lastX, lastY);  
  99.         }  
  100.         else  
  101.         {  
  102.             DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y);  
  103.             frontC = (frontC + 1) % 4;  
  104.         }  
  105.   
  106.         EndPaint(hwnd, &ps);  
  107.         return 0;  
  108.   
  109.     //用键盘控制位图的显示  
  110.     case WM_KEYDOWN:  
  111.         hdc = GetDC(hwnd);  
  112.   
  113.         switch(wParam)  
  114.         {  
  115.         //向前  
  116.         case VK_UP:  
  117.             frontC=leftC=rightC=0;//清空除当前方向的所有计数  
  118.               
  119.             //控制移动的距离  
  120.             if(!(rearC % 2))  
  121.             {  
  122.                 y -= 10;  
  123.             }  
  124.             else  
  125.             {  
  126.                 y -= 2;  
  127.             }  
  128.   
  129.             DrawBitmap(hInstance, hdc, DIR_REAR, rearC, x, y);  
  130.             rearC = (rearC+1) % 4;  
  131.               
  132.             break;  
  133.   
  134.         //向后  
  135.         case VK_DOWN:  
  136.             rearC=leftC=rightC=0;  
  137.   
  138.             //控制移动的距离  
  139.             if(!(frontC % 2))  
  140.             {  
  141.                 y += 10;  
  142.             }  
  143.             else  
  144.             {  
  145.                 y += 2;  
  146.             }  
  147.   
  148.             DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y);  
  149.             frontC = (frontC+1) % 4;  
  150.   
  151.             break;  
  152.   
  153.         //向左  
  154.         case VK_LEFT:  
  155.             frontC=rearC=rightC=0;  
  156.   
  157.             //控制移动的距离  
  158.             if(!(leftC % 2))  
  159.             {  
  160.                 x -= 15;  
  161.             }  
  162.             else  
  163.             {  
  164.                 x -= 3;  
  165.             }  
  166.   
  167.             DrawBitmap(hInstance, hdc, DIR_LEFT, leftC, x, y);            
  168.             leftC = (leftC+1) % 4;  
  169.               
  170.             break;  
  171.   
  172.         //向右  
  173.         case VK_RIGHT:  
  174.             frontC=rearC=leftC=0;  
  175.   
  176.             //控制移动的距离  
  177.             if(!(rightC % 2))  
  178.             {  
  179.                 x += 15;  
  180.             }  
  181.             else  
  182.             {  
  183.                 x += 3;  
  184.             }  
  185.   
  186.             DrawBitmap(hInstance, hdc, DIR_RIGHT, rightC, x, y);  
  187.             rightC = (rightC+1) % 4;  
  188.   
  189.             break;  
  190.         }  
  191.         ReleaseDC(hwnd, hdc);  
  192.         return 0;  
  193.   
  194.     case WM_DESTROY:  
  195.         PostQuitMessage(0);  
  196.         return 0;  
  197.     }  
  198.   
  199.     return DefWindowProc(hwnd, message, wParam, lParam);  
  200. }  
  201.   
  202. IDB_BITMAP GetBitmapID(int dir, int dirCount)  
  203. {  
  204.     return 101 + dir*4 + dirCount;  
  205. }  
  206.   
  207. //绘制位图  
  208. void DrawBitmap(HINSTANCE hInstance, HDC hdc, int dir, int dirCount, int x, int y)  
  209. {  
  210.     HBITMAP hBitmap;  
  211.     BITMAP  bitmap;  
  212.     HDC     hdcMem;  
  213.   
  214.     //用于创建和hdc兼容的内存设备控制表句柄  也就相当于在内存中绘图,一个缓冲(当然,位图也能支持"截图")  
  215.     hdcMem = CreateCompatibleDC(hdc);  
  216.   
  217.     hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(GetBitmapID(dir, dirCount)));  
  218.     GetObject(hBitmap, sizeof(BITMAP), &bitmap);  
  219.     SelectObject(hdcMem, hBitmap);  
  220.   
  221.     //清除上一步位图信息  
  222.     if(lastBitmap.bmWidth)  
  223.     {  
  224.         BitBlt(hdc, lastX - 1, lastY - 1, lastBitmap.bmWidth + 1, lastBitmap.bmHeight + 1, hdcMem, 0, 0, WHITENESS);  
  225.     }  
  226.   
  227.     //保存上一步信息  
  228.     lastX = x;  
  229.     lastY = y;  
  230.     lastDir = dir;  
  231.     lastDirCount = dirCount;  
  232.     lastBitmap = bitmap;  
  233.   
  234.     //绘制当前位图信息  
  235.     BitBlt(hdc, x, y, bitmap.bmWidth - 1, bitmap.bmHeight - 1, hdcMem, 0, 0, SRCCOPY);  
  236.   
  237.     DeleteObject(hBitmap);  
  238.     DeleteDC(hdcMem);  
  239. }  


 

运行效果:


download

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值