Visual C++游戏编程基础之键盘消息

一、键盘

1.虚拟键码:Windows系统下所有的按键被视为虚拟键(包含鼠标在内),每一个虚拟键都有其对应的虚拟键码;

2.键盘消息

(1)VM_KEWDOWN:按下按键消息;

(2)VM_KEYUP       :松开按键消息;

(3)VM_CHAR         :字符消息,当按下的按键为定义于ASCII码中的可打印字符时,便发出此字符消息;

3.系统键

(1)VM_SYSKEYDOWN:按下系统键消息;

(2)VM_SYSKEYUP      :松开系统键消息;

二、键盘消息处理

1.LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

(1)wParam:表示按下按键的虚拟键码;

(2)lParam  :存储按键的相关状态信息;

三、利用键盘上、下、左、右控制人物

1.首先设置人物的起始贴图坐标和起始方向,用0、1、2、3表示上、下、左、右,起始设为0;

2.初始化函数中,除贴背景图外,根据方向选择要贴的人物,还有根据方向判断人物图的宽和高,以便进行透明处理和贴图

   操作,此时若没有按键操作,WinMain函数将每隔一段时间进行贴图操作,从而实现了人物的原地跑动;

3.若此时按下向下的按键,消息处理函数接收按键消息,接着要判断当前人物所处的方向,根据不同的方向,适当修正,只要有

   明显下移就可以,然后判断y的值不能比地图的高还大,要设临界值;

4.更改了贴图坐标后,把方向设为1(下是1),然后就去指向绘图函数,然后又是重复2的操作;

四、效果

五、代码如下


#include "stdafx.h"
#include <stdio.h>

HINSTANCE hInst;
HBITMAP girl[4],bg;
HDC		hdc,mdc,bufdc;
HWND	hWnd;
DWORD	tPre,tNow;
int		num,dir,x,y;//num:连续图中的小图编号;dir:人物移动的方向;x,y为人物贴图坐标

ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
void				MyPaint(HDC hdc);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	MSG msg;

	MyRegisterClass(hInstance);


	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}


    while( msg.message!=WM_QUIT )
    {
        if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
		else
		{
			tNow = GetTickCount();
			if(tNow-tPre >= 40)
				MyPaint(hdc);
		}
    }

	return msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= NULL;
	wcex.hCursor		= NULL;
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= "canvas";
	wcex.hIconSm		= NULL;

	return RegisterClassEx(&wcex);
}


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HBITMAP bmp;
	hInst = hInstance;

	hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	if (!hWnd)
	{
		return FALSE;
	}

	MoveWindow(hWnd,10,10,640,500,true);
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	hdc = GetDC(hWnd);
	mdc = CreateCompatibleDC(hdc);
	bufdc = CreateCompatibleDC(hdc);

	bmp = CreateCompatibleBitmap(hdc,640,480);
	SelectObject(mdc,bmp);

	x = 300;
	y = 250;//人物的起始贴图位置(300,250)
	dir = 0;//起始面向上
	num = 0;

	girl[0] = (HBITMAP)LoadImage(NULL,"girl0.bmp",IMAGE_BITMAP,440,148,LR_LOADFROMFILE);
	girl[1] = (HBITMAP)LoadImage(NULL,"girl1.bmp",IMAGE_BITMAP,424,154,LR_LOADFROMFILE);
	girl[2] = (HBITMAP)LoadImage(NULL,"girl2.bmp",IMAGE_BITMAP,480,148,LR_LOADFROMFILE);
	girl[3] = (HBITMAP)LoadImage(NULL,"girl3.bmp",IMAGE_BITMAP,480,148,LR_LOADFROMFILE);
	bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,640,480,LR_LOADFROMFILE);

	MyPaint(hdc);

	return TRUE;
}


void MyPaint(HDC hdc)
{
	int w,h;

	SelectObject(bufdc,bg);
	BitBlt(mdc,0,0,640,480,bufdc,0,0,SRCCOPY);

	SelectObject(bufdc,girl[dir]);
	switch(dir)
	{
		case 0:
			w = 55;
			h = 74;
			break;
		case 1:
			w = 53;
			h = 77;
			break;
		case 2:
			w = 60;
			h = 74;
			break;
		case 3:
			w = 60;
			h = 74;
			break;
	}
	BitBlt(mdc,x,y,w,h,bufdc,num*w,h,SRCAND);
	BitBlt(mdc,x,y,w,h,bufdc,num*w,0,SRCPAINT);
	
	BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);

	tPre = GetTickCount();         

	num++;
	if(num == 8)
		num = 0;

}

//Esc键结束程序
//方向键重设贴图坐标
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_KEYDOWN:			      
			switch (wParam) 
			{
				case VK_ESCAPE:           
					PostQuitMessage( 0 );
					break;
				case VK_UP:				  
					switch(dir)
					{
						case 0:	
							y -= 10;
							break;
						case 1:
							x -= 1;
							y -= 8;
							break;
						case 2:	
							x += 2;
							y -= 10;
							break;
						case 3:
							x += 2;
							y -= 10;
							break;
					}
					if(y < 0)
						y = 0;
					dir = 0;
					break;
				case VK_DOWN:			 
					switch(dir)
					{
						case 0:
							x += 1;
							y += 8;
							break;
						case 1:
							y += 10;
							break;
						case 2:
							x += 3;
							y += 6;
							break;
						case 3:
							x += 3;
							y += 6;
							break;
					}

					if(y > 375)
						y = 375;
					dir = 1;
					break;
				case VK_LEFT:			  
					switch(dir)
					{
						case 0:
							x -= 12;
							break;
						case 1:
							x -= 13;
							y += 4;
							break;
						case 2:
							x -= 10;
							break;
						case 3:
							x -= 10;
							break;
					}
					if(x < 0)
						x = 0;
					dir = 2;
					break;
				case VK_RIGHT:			   
					switch(dir)
					{
						case 0:
							x += 8;
							break;
						case 1:
							x += 7;
							y += 4;
							break;
						case 2:
							x += 10;
							break;
						case 3:
							x += 10;
							break;
					}
					if(x > 575)  //640-60
						x = 575;
					dir = 3;
					break;
			}
			break;
		case WM_DESTROY:			    	
			int i;

			DeleteDC(mdc);
			DeleteDC(bufdc);
			for(i=0;i<4;i++)
				DeleteObject(girl[i]);
			DeleteObject(bg);
			ReleaseDC(hWnd,hdc);

			PostQuitMessage(0);
			break;
		default:							
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

 

猜你喜欢

转载自blog.csdn.net/Sruggle/article/details/91357275
今日推荐