本文由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);
}
运行效果:
点击下载位图资源