本文由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);
}
運行效果:
點擊下載位圖資源