Bitmap位圖應用2 ------ 鍵盤控制人物走動

本文由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);
}


 

運行效果:

 

 

點擊下載位圖資源
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章