本文由BlueCoder编写 转载请说明出处:
http://blog.csdn.net/crocodile__/article/details/9451251
我的邮箱:[email protected] 欢迎大家和我交流编程心得
我的微博:BlueCoder_黎小华 欢迎光临^_^
今天掌握了Bitmap的用法,忍不住再来一次升级版的应用------用键盘控制人物的走动,这个可能在游戏设计中用的很多,不过今儿就先来小试牛刀,呵呵……
本人学习编程有个"癖好" —— 那就是有了想法,下一步就是实现,越快实现越好,不实现就誓不罢休……
好了,F话少说了,还是先来逐步了解需求吧
(1)首先需要一个完整的人物走路分解图,每一个方向4张,分别是:直立、右脚向前、直立、左脚向前
(资源由本人亲自制作,待会儿上传^_^)
(2)加载位图到内存中,这个和Bitmap应用1一样,不再赘述
(3)获取位图ID
首先需要写两个方法:
IDB_BITMAP GetBitmapID(int dir, int dirCount); //获取当前绘制的位图ID void DrawBitmap(HINSTANCE, HDC, int, int, int, int); //绘制位图 (IDB_BITMAP就是int)
本程序总共需要16张位图,位图ID是从101开始,每一张是紧挨着的(101~116),所以可以通过ID这个特点来控制位图的选择
GetBitmapID()的参数dir取以下4个之1:(位图的排列顺序为: 前后左右)
//位图的方位 #define DIR_FRONT 0 #define DIR_REAR 1 #define DIR_LEFT 2 #define DIR_RIGHT 3
参数dirCount取以下4个之1(也就是方向键连续按下的次数,每次对4求余数,因为每一个方向有4张分解图)
static int frontC, rearC, leftC, rightC; //计数是为了控制每个方向所显示状态(立正、右脚向前、立正、左脚向前)
然后简单的运算就能得到相应的位图ID号:
101 + dir*4 + dirCount
(4)用键盘控制人物的走动
由于每一个方向的处理类似,这里就简述一下向前走的控制算法:
rearC=leftC=rightC=0;//清除 //控制移动的距离 if(!(frontC % 2)) //当人物直立时,移动距离控制为10 { y += 10; } else //当人物左脚或右脚向前时,移动距离控制为2 这是经过多次测试得到的数据,这样控制的效果较好 { y += 2; } DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y);//绘制人物的状态 frontC = (frontC+1) % 4;//计算本方向(如果继续按下Dowm键)的下一次移动
(5)清除上一步的状态,也就是将上一步的位图刷掉
方法还是调用BitBlt()方法,只不过是绘制一块白色的位图,仅仅需要将最后一个参数设定为WHITENESS就ok了
好了这就是全过程,以下就是完整代码:
//前后左右移动的小猫 #include<windows.h> #include<stdio.h> #include"resource.h" //位图的方位 #define DIR_FRONT 0 #define DIR_REAR 1 #define DIR_LEFT 2 #define DIR_RIGHT 3 //类型的重定义 typedef int IDB_BITMAP; /** 为重绘保存上一步的信息 **/ //保存上一步的位图 BITMAP lastBitmap; //保存上一步位图的坐标 int lastX, lastY; //保存上一步位图的方向和按键计数 int lastDir, lastDirCount; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); IDB_BITMAP GetBitmapID(int, int); //获取当前绘制的位图ID void DrawBitmap(HINSTANCE, HDC, int, int, int, int); //绘制位图 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("MoveCat"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if(!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("MoveCat Demo"), WS_OVERLAPPEDWINDOW, (1366 - 720) / 2, (768 - 570) / 2, 720, 570, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HINSTANCE hInstance;//窗口的实例句柄 static int frontC, rearC, leftC, rightC, x, y; //分别表示方位键按键计数和位图显示的位置 计数是为了控制每个方向所显示状态(立正、右脚向前、立正、左脚向前) HDC hdc; PAINTSTRUCT ps; switch(message) { case WM_CREATE: hInstance = ((LPCREATESTRUCT)lParam)->hInstance; return 0 ; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); if(lastBitmap.bmWidth) { DrawBitmap(hInstance, hdc, lastDir, lastDirCount, lastX, lastY); } else { DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y); frontC = (frontC + 1) % 4; } EndPaint(hwnd, &ps); return 0; //用键盘控制位图的显示 case WM_KEYDOWN: hdc = GetDC(hwnd); switch(wParam) { //向前 case VK_UP: frontC=leftC=rightC=0;//清空除当前方向的所有计数 //控制移动的距离 if(!(rearC % 2)) { y -= 10; } else { y -= 2; } DrawBitmap(hInstance, hdc, DIR_REAR, rearC, x, y); rearC = (rearC+1) % 4; break; //向后 case VK_DOWN: rearC=leftC=rightC=0; //控制移动的距离 if(!(frontC % 2)) { y += 10; } else { y += 2; } DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y); frontC = (frontC+1) % 4; break; //向左 case VK_LEFT: frontC=rearC=rightC=0; //控制移动的距离 if(!(leftC % 2)) { x -= 15; } else { x -= 3; } DrawBitmap(hInstance, hdc, DIR_LEFT, leftC, x, y); leftC = (leftC+1) % 4; break; //向右 case VK_RIGHT: frontC=rearC=leftC=0; //控制移动的距离 if(!(rightC % 2)) { x += 15; } else { x += 3; } DrawBitmap(hInstance, hdc, DIR_RIGHT, rightC, x, y); rightC = (rightC+1) % 4; break; } ReleaseDC(hwnd, hdc); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } IDB_BITMAP GetBitmapID(int dir, int dirCount) { return 101 + dir*4 + dirCount; } //绘制位图 void DrawBitmap(HINSTANCE hInstance, HDC hdc, int dir, int dirCount, int x, int y) { HBITMAP hBitmap; BITMAP bitmap; HDC hdcMem; //用于创建和hdc兼容的内存设备控制表句柄 也就相当于在内存中绘图,一个缓冲(当然,位图也能支持"截图") hdcMem = CreateCompatibleDC(hdc); hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(GetBitmapID(dir, dirCount))); GetObject(hBitmap, sizeof(BITMAP), &bitmap); SelectObject(hdcMem, hBitmap); //清除上一步位图信息 if(lastBitmap.bmWidth) { BitBlt(hdc, lastX - 1, lastY - 1, lastBitmap.bmWidth + 1, lastBitmap.bmHeight + 1, hdcMem, 0, 0, WHITENESS); } //保存上一步信息 lastX = x; lastY = y; lastDir = dir; lastDirCount = dirCount; lastBitmap = bitmap; //绘制当前位图信息 BitBlt(hdc, x, y, bitmap.bmWidth - 1, bitmap.bmHeight - 1, hdcMem, 0, 0, SRCCOPY); DeleteObject(hBitmap); DeleteDC(hdcMem); }
运行效果:
点击下载位图资源