利用VS创建一个游戏(6)计算机角色动画之恐龙乐园(代码+注释)

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

//恐龙结构体
struct dragon
{
	int x, y;//恐龙窗口
	int dir;//方向
};

//全局变量
HWND              hWnd;
HINSTANCE         hInst;
HDC               hdc, mdc, bufdc;
HBITMAP           bg, draPic[4];
int               picNum;
DWORD             tPre, tNow;
BOOL              bPause = FALSE;
const int         draNum = 10;
dragon            dra[draNum];
int               i;


// 此代码模块中包含的函数的前向声明:     
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitWindow(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
VOID                CartoonPaint(HDC hdc);
void                Sort(int n);

int APIENTRY WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR    lpCmdLine,
	int       nCmdShow)
{
	// 初始化全局字符串    
	MyRegisterClass(hInstance);

	// 执行应用程序初始化:     
	if (!InitWindow(hInstance, nCmdShow))//初始化窗口    
	{
		return FALSE;//如果不成功则返回FALSE,并退出程序    
	}

	MSG msg; //创建消息类对象    

			 // TODO: 在此放置运行代码。

			 //定义局部变量
	HBITMAP           bmp;

	//建立内存DC和窗口DC
	hdc = GetDC(hWnd);
	mdc = CreateCompatibleDC(hdc);
	bufdc = CreateCompatibleDC(hdc);

	//建立适用位图
	bmp = CreateCompatibleBitmap(hdc, 640, 480);
	SelectObject(mdc, bmp);

	//加载图片
	bg = (HBITMAP)LoadImage(NULL, "bg.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE);
	draPic[0] = (HBITMAP)LoadImage(NULL, "dra0.bmp", IMAGE_BITMAP, 528, 188, LR_LOADFROMFILE);
	draPic[1] = (HBITMAP)LoadImage(NULL, "dra1.bmp", IMAGE_BITMAP, 544, 164, LR_LOADFROMFILE);
	draPic[2] = (HBITMAP)LoadImage(NULL, "dra2.bmp", IMAGE_BITMAP, 760, 198, LR_LOADFROMFILE);
	draPic[3] = (HBITMAP)LoadImage(NULL, "dra3.bmp", IMAGE_BITMAP, 760, 198, LR_LOADFROMFILE);

	//定义恐龙初始方向和位置
	for (i = 0; i<draNum; i++)
	{
		dra[i].dir = 3;
		dra[i].x = 200;
		dra[i].y = 200;
	}

	//绘制恐龙
	CartoonPaint(hdc);

	// 主消息循环:     
	PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//赋初值    

	while (msg.message != WM_QUIT)         //进入游戏消息循环:    
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg); //获得游戏玩家输入的消息;    
			DispatchMessage(&msg);//分配玩家消息并响应用户消息。    
		}
		else
		{
			tNow = GetTickCount();
			if (tNow - tPre >= 100)
				if (bPause)
					CartoonPaint(hdc);

		}
	}

	return (int)msg.wParam;
}



//    
//  函数: MyRegisterClass()    
//    
//  注册Windows类,一款游戏有且仅有一个主窗口,与游戏程序唯一对应。创建游戏窗口前要填写窗口类结构体WNDCLASSEX    
//    
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex =
	{
		wcex.cbSize = sizeof(WNDCLASSEX),


		CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,

		WndProc,0,0,

		hInstance,

		LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)),

		LoadCursor(NULL, IDC_ARROW),


		(HBRUSH)(COLOR_WINDOW + 1),NULL,

		_T("GameFrame"),

		LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL))
	};
	return RegisterClassEx(&wcex);
}

//    
//   函数: InitInstance(HINSTANCE, int)    
//    
//   目的: 保存实例句柄并创建主窗口    
//    
//   注释:     
//    
//        在此函数中,我们在全局变量中保存实例句柄并    
//        创建和显示主程序窗口。    
//    
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
	hInst = hInstance; // 将实例句柄存储在全局变量中    

	hWnd = CreateWindow
	(
		_T("GameFrame"),
		_T("游戏框架"),
		WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通样式,不能改变大小,不能最大化    
		CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, nullptr, nullptr, hInstance, nullptr
	);

	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}

//    
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)    
//    
//  目的:    处理主窗口的消息。    
//    
//  WM_COMMAND  - 处理应用程序菜单    
//  WM_PAINT    - 绘制主窗口    
//  WM_DESTROY  - 发送退出消息并返回    
//    
//    
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	PAINTSTRUCT ps;                     //用于WM_PAINT    
	HDC hdc;                            //设备场景句柄    
	switch (msg)                        //判断消息    
	{
	case WM_CREATE:
		//执行初始化代码                  
		return(0);
		break;
		//键盘控制龙运动或静止
	case WM_CHAR:
		bPause = !bPause;
		break;

	case WM_PAINT:
		//确定窗口是否有效    
		hdc = BeginPaint(hwnd, &ps);
		//TODO:添加执行绘制代码    

		//结束代码    
		EndPaint(hwnd, &ps);
		return(0);
		break;
	case WM_DESTROY:
		//关闭程序,发送WM_QUIT消息    
		PostQuitMessage(0);
		return(0);
		break;
	default:
		break;
	}
	return (DefWindowProc(hwnd, msg, wparam, lparam));
}
void CartoonPaint(HDC hdc)
{
	//图片大小
	int w, h;

	//动作循环
	if (picNum == 8)
		picNum = 0;

	//绘制背景
	SelectObject(bufdc, bg);
	BitBlt(mdc, 0, 0, 640, 480, bufdc, 0, 0, SRCCOPY);

	Sort(draNum); //以Y 轴坐标进行排序

	for (i = 0; i < draNum; i++)
	{
		SelectObject(bufdc, draPic[dra[i].dir]);


		//对窗口中跑动的恐龙进行贴图
		switch (dra[i].dir)
		{
			//前
		case 0:
			w = 66;
			h = 94;
			break;
			//后
		case 1:
			w = 68;
			h = 82;
			break;
			//左
		case 2:
			w = 95;
			h = 99;
			break;
			//右
		case 3:
			w = 95;
			h = 99;
			break;
		}

		//半透明处理
		BitBlt(mdc, dra[i].x, dra[i].y, w, h, bufdc, picNum*w, h, SRCAND);
		BitBlt(mdc, dra[i].x, dra[i].y, w, h, bufdc, picNum*w, 0, SRCPAINT);
	}

	BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY);
	tPre = GetTickCount();
	picNum++;

	for (i = 0; i < draNum; i++)
	{
		// 计算移动过的绘图坐标,同时进行误差的校正
		int nDir = rand() % 4;

		//改变随机转换方向的几率
		if (rand() % 3 != 0)
			nDir = dra[i].dir;

		switch (nDir) {
			//由前变为
		case 0:                                                               //上
			switch (dra[i].dir) {
			case 0:
				dra[i].y -= 20;
				break;
			case 1:
				dra[i].x += 2;
				dra[i].y -= 31;
				break;
			case 2:
				dra[i].x += 14;
				dra[i].y -= 20;
				break;
			case 3:
				dra[i].x += 14;
				dra[i].y -= 20;
				break;
			}
			if (dra[i].y < 0)
				dra[i].y = 0;
			dra[i].dir = 0;
			break;
			//由后变为
		case 1:                                                                 //下 
			switch (dra[i].dir)
			{
			case 0:
				dra[i].x -= 2;
				dra[i].y += 31;
				break;
			case 1:
				dra[i].y += 20;
				break;
			case 2:
				dra[i].x += 15;
				dra[i].y += 29;
				break;
			case 3:
				dra[i].x += 15;
				dra[i].y += 29;
				break;
			}
			if (dra[i].y > 370)    dra[i].y = 370;
			dra[i].dir = 1;
			break;
			//由左变为
		case 2:                                                                   //左
			switch (dra[i].dir)
			{
			case 0:
				dra[i].x -= 34;
				break;
			case 1:
				dra[i].x -= 34;
				dra[i].y -= 9;
				break;
			case 2:
				dra[i].x -= 20;
				break;
			case 3:
				dra[i].x -= 20;
				break;
			}
			if (dra[i].x < 0)      dra[i].x = 0;
			dra[i].dir = 2;
			break;
			//由右变为
		case 3:                                                                   //右
			switch (dra[i].dir) {
			case 0:
				dra[i].x += 6;
				break;
			case 1:
				dra[i].x += 6;
				dra[i].y -= 10;
			break;			        case 2:
				dra[i].x += 20;
				break;
			case 3:
				dra[i].x += 20;
				break;
			}
			if (dra[i].x > 535)
				dra[i].x = 535;
			dra[i].dir = 3;
			break;
		}
	}
}
//对小恐龙们进行视觉上的排序,使其看起来自然
void Sort(int n) {
	int i, j;
	bool f;
	dragon tmp;
	for (i = 0; i<n - 1; i++)
	{
		f = false;
		for (j = 0; j<n - i - 1; j++)
		{
			if (dra[j + 1].y < dra[j].y)
			{
				tmp = dra[j + 1];
				dra[j + 1] = dra[j];
				dra[j] = tmp;
				f = true;
			}
		}
		if (!f)
			break;
	}
}


猜你喜欢

转载自blog.csdn.net/hao5119266/article/details/80397140
今日推荐