【游戏开发】简易控制人物行走


//Windows窗口头文件
#include <windows.h>

//使用swprintf_s函数所需的头文件
#include <tchar.h>

//PlaySound函数包含的头文件
#pragma comment(lib,"winmm.lib")	

//TransparentBlt函数包含的库文件
#pragma  comment(lib,"Msimg32.lib")

//窗口宽度
#define WINDOW_WIDTH	800							

//窗口高度
#define WINDOW_HEIGHT	600							

//窗口标题
#define WINDOW_TITLE		L"【游戏开发】简易控制人物行走 "

//全局环境设备,全局内存设备,全局缓存设备
HDC				g_hdc=NULL,g_mdc=NULL,g_bufdc=NULL;    

//4张方向图,1张背景图
HBITMAP		g_hSprite[4]={NULL},g_hBackGround=NULL;	

//上一次绘图时间,当前绘图时间
DWORD		g_tPre=0,g_tNow=0;		

//记录的图号,横纵坐标
int					g_iNum=0,g_iX=0,g_iY=0;         

//人物移动方向,0,1,2,3代表人物上,下,左,右方向上的移动
int					g_iDirection=0;

//窗口过程函数
LRESULT CALLBACK	WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );

//初始化资源
BOOL						Game_Init(HWND hwnd);			

//绘图
VOID							Game_Paint( HWND hwnd);		

//清理资源
BOOL						Game_CleanUp(HWND hwnd );

//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{
	//定义窗口类
	WNDCLASSEX wndClass = { 0 };

	//结构体的字节数大小
	wndClass.cbSize = sizeof( WNDCLASSEX ) ;

	//窗口的样式
	wndClass.style = CS_HREDRAW | CS_VREDRAW;

	//指向窗口过程函数的指针
	wndClass.lpfnWndProc = WndProc;			

	//窗口类的附加内存,取0
	wndClass.cbClsExtra		= 0;		
	
	//窗口的附加内存,依然取0
	wndClass.cbWndExtra		= 0;

	//窗口过程的程序的实例句柄
	wndClass.hInstance = hInstance;				
	
	//ico图标
	wndClass.hIcon=(HICON)::LoadImage(NULL,L"icon.ico",IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE); 

	//光标句柄
	wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );  

	//画刷句柄
	wndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); 

	//菜单资源的名字
	wndClass.lpszMenuName = NULL;					

	//窗口类的名字
	wndClass.lpszClassName = L"TWJDWQ";		//用一个以空终止的字符串,。

	//注册窗口类
	if( !RegisterClassEx( &wndClass ) )			
		return -1;		

	//创建窗口
	HWND hwnd = CreateWindow( L"TWJDWQ",WINDOW_TITLE,			
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
		WINDOW_HEIGHT, NULL, NULL, hInstance, NULL );

	//移动窗口
	MoveWindow(hwnd,250,80,WINDOW_WIDTH,WINDOW_HEIGHT,true);

	//显示窗口
	ShowWindow( hwnd, nShowCmd );  

	//更新窗口
	UpdateWindow(hwnd);		

	//初始化游戏资源
	if (!Game_Init (hwnd)) 
	{
		//消息窗口
		MessageBox(hwnd, L"资源初始化失败", L"消息窗口", 0);
		return FALSE;
	}

	//循环播放背景音乐
	PlaySound(L"徐鲤 - 大理1.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);  

	//定义并初始化msg
	MSG msg = { 0 };	

	//消息循环
	while( msg.message != WM_QUIT )	
	{
		//查看并派发消息
		if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )   
		{
			//将虚拟键消息转换为字符消息
			TranslateMessage( &msg );	

			//捕捉消息给窗口
			DispatchMessage( &msg );		
		}
		else
		{
			//获取当前系统时间
			g_tNow = GetTickCount();  

			//当此次循环运行与上次绘图时间相差0.05秒时再进行重绘操作
			if(g_tNow-g_tPre >= 50)        
				Game_Paint(hwnd);
		}

	}

	//注销窗口类
	UnregisterClass(L"TWJDWQ", wndClass.hInstance); 
	return 0;  
}

//处理窗口消息
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )      
{

	switch( message )			
	{
	//按键
	case WM_KEYDOWN:	    

		//判断按键的虚拟键码
		switch (wParam) 
		{
		//按下【Esc】键
		case VK_ESCAPE:           

			//销毁窗口, 并发送一条WM_DESTROY消息
			DestroyWindow(hwnd);

			//结束程序
			PostQuitMessage( 0 );  
			break;

		//按下【↑】键
		case VK_UP:		

			//根据按键加入人物移动的量(每次按下一次按键移动10个单位),来决定人物贴图坐标的X与Y值,接着判断坐标是否超出窗口区域,若有则进行修正
			g_iY -= 10;
			g_iDirection = 0;
			if(g_iY < 0)
				g_iY = 0;
			break;

		//按下【↓】键
		case VK_DOWN:			 
			g_iY += 10;
			g_iDirection = 1;
			if(g_iY > WINDOW_HEIGHT-135)
				g_iY = WINDOW_HEIGHT-135;	
			break;

		//按下【←】键
		case VK_LEFT:			  			
			g_iX -= 10;
			g_iDirection = 2;
			if(g_iX < 0)
				g_iX = 0;		
			break;

		//按下【→】键
		case VK_RIGHT:			   
			g_iX += 10;
			g_iDirection = 3;
			if(g_iX > WINDOW_WIDTH-75)
				g_iX = WINDOW_WIDTH-75;
			break;
		}			
		break;			

	//窗口销毁消息
	case WM_DESTROY:	

		//清理资源
		Game_CleanUp(hwnd);			

		//结束程序
		PostQuitMessage( 0 );			
		break;							

	//缺省
	default:										
		return DefWindowProc( hwnd, message, wParam, lParam );		

	}

	return 0;							
}

//初始化游戏资源
BOOL Game_Init( HWND hwnd )
{
	//背景位图
	HBITMAP bmp;

	//环境设备
	g_hdc = GetDC(hwnd);  

	//内存设备(与环境设备兼容)
	g_mdc = CreateCompatibleDC(g_hdc); 

	//缓存设备(与环境设备兼容)
	g_bufdc = CreateCompatibleDC(g_hdc);

	//背景位图
	bmp = CreateCompatibleBitmap(g_hdc,WINDOW_WIDTH,WINDOW_HEIGHT);

	//设定人物贴图初始位置和移动方向
	g_iX = 150;
	g_iY = 350;
	g_iDirection = 3;
	g_iNum = 0;

	//把背景选入缓存设备中
	SelectObject(g_mdc,bmp);

	//加载各张跑动图及背景图,这里以0,1,2,3来代表人物上,下,左,右移动
	g_hSprite[0] = (HBITMAP)LoadImage(NULL,L"上1.bmp",IMAGE_BITMAP,420,230,LR_LOADFROMFILE);
	g_hSprite[1] = (HBITMAP)LoadImage(NULL,L"下2.bmp",IMAGE_BITMAP,420,230,LR_LOADFROMFILE);
	g_hSprite[2] = (HBITMAP)LoadImage(NULL,L"左3.bmp",IMAGE_BITMAP,420,230,LR_LOADFROMFILE);
	g_hSprite[3] = (HBITMAP)LoadImage(NULL,L"右4.bmp",IMAGE_BITMAP,420,230,LR_LOADFROMFILE);
	g_hBackGround = (HBITMAP)LoadImage(NULL,L"bg.bmp",IMAGE_BITMAP,WINDOW_WIDTH,WINDOW_HEIGHT,LR_LOADFROMFILE);

	Game_Paint(hwnd);
	return TRUE;
}

//
VOID Game_Paint( HWND hwnd )
{
	//先在mdc中贴上背景图
	SelectObject(g_bufdc,g_hBackGround);
	BitBlt(g_mdc,0,0,WINDOW_WIDTH,WINDOW_HEIGHT,g_bufdc,0,0,SRCCOPY);

	//按照目前的移动方向取出对应人物的连续走动图,并确定截取人物图的宽度与高度
	SelectObject(g_bufdc,g_hSprite[g_iDirection]);
	BitBlt(g_mdc,g_iX,g_iY,105,115,g_bufdc,g_iNum*105,115,SRCAND);
	BitBlt(g_mdc,g_iX,g_iY,105,115,g_bufdc,g_iNum*105,0,SRCPAINT);

	//将最后的画面显示在窗口中
	BitBlt(g_hdc,0,0,WINDOW_WIDTH,WINDOW_HEIGHT,g_mdc,0,0,SRCCOPY);

	//记录此次绘图时间
	g_tPre = GetTickCount();     
	g_iNum++;

	//一个方向4种位图
	if(g_iNum == 4)
		g_iNum = 0;

}

//清理游戏资源
BOOL Game_CleanUp( HWND hwnd )
{
	//释放资源对象
	DeleteObject(g_hBackGround);
	for (int i=0;i<4;i++)
	{
		DeleteObject(g_hSprite[i]);
	}
	DeleteDC(g_bufdc);
	DeleteDC(g_mdc);
	ReleaseDC(hwnd,g_hdc);
	return TRUE;
}

猜你喜欢

转载自blog.csdn.net/qq_23996157/article/details/87891147
今日推荐