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

本文由BlueCoder编写   转载请说明出处:

http://blog.csdn.net/crocodile__/article/details/9451251

我的邮箱:bluecoder@yeah.net    欢迎大家和我交流编程心得

我的微博: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);
}


 

运行效果:

 

 

点击下载位图资源
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值