利用VS创建一个游戏(5)计算机角色动画之打飞机(代码+注释)

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

//子弹结构体
struct BULLET
{
	int x, y;
	bool exist;
};

//全局变量
HWND              hWnd;
HINSTANCE         hInst;
HDC               hdc, mdc,bufdc;
HBITMAP           bg,ship,bullet;
int               x, y, nowX, nowY;
int               bcount;                   //子弹数目;
int               w = 0;
DWORD             tPre, tNow;
BULLET            b[30];


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

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;
	POINT             pt, lt, rb;

	/*
	typedef struct tagRECT
	{
	LONG    left;
	LONG    top;
	LONG    right;
	LONG    bottom;
	} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;
	RECT结构定义了一个矩形框左上角以及右下角的坐标
	*/
	RECT              rect;

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

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

	//加载图片
	bg = (HBITMAP)LoadImage(NULL, "sky.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE);
	ship = (HBITMAP)LoadImage(NULL, "ship.bmp", IMAGE_BITMAP, 100, 148, LR_LOADFROMFILE);
	bullet = (HBITMAP)LoadImage(NULL, "bullet.bmp", IMAGE_BITMAP, 10, 20, LR_LOADFROMFILE);

    //定义鼠标初始位置
	x = 300;
	y = 300;

	//定义飞机初始位置
	nowX = 300;
	nowY = 300;

	//定义鼠标光标位置
	pt.x = 300;
	pt.y = 300;

	//把窗口坐标转换为屏幕坐标
	ClientToScreen(hWnd, &pt);

	//设定光标位置
	//SetCursorPos该函数把光标移到屏幕的指定位置(参数均为屏幕坐标)。
	//如果新位置不在由 ClipCursor()函数设置的屏幕矩形区域之内,则系统自动调整坐标,使得光标在矩形之内。
	SetCursorPos(pt.x, pt.y);

	//显示光标
	ShowCursor(true);

	//限制鼠标光标仅仅在游戏窗口内移动
	//GetClientRect用于取得指定窗口的客户区域大小
	//每个窗口区域可分为两部分,用于显示内容的区域叫Client区(客户区),NonClient(非客户区)用于显示命令按钮及窗口标题等。
	//非客户区的绘图是由WM_NCPAINT发出的。
	GetClientRect(hWnd, &rect);

	lt.x = rect.left;
	lt.y = rect.top;
	rb.x = rect.right;
	rb.y = rect.bottom;

	//转化坐标
	ClientToScreen(hWnd, &lt);
	ClientToScreen(hWnd, &rb);

	rect.left = lt.x;
	rect.top = lt.y;
	rect.right = rb.x;
	rect.bottom = rb.y;

	//设置区域大小
	ClipCursor(&rect);

	//绘图
	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 >= 20)
				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_MOUSEMOVE:
		//获取鼠标X坐标
		x = LOWORD(lparam);
		if (x > 530)
			x = 530;
		else if (x < 0)
			x = 0;
		//获取鼠标Y坐标
		y = HIWORD(lparam);
		if (y > 380)
			y = 380;
		else  if (y < 0)
			y = 0;
		break;
        //鼠标左键控制
	case WM_LBUTTONDOWN:
		for (int i = 0; i < 30; i++)
		{
			if (!b[i].exist) 
			{
				b[i].x = nowX;
				b[i].y = nowY + 30;//子弹Y坐标修正
				b[i].exist = true;
				bcount++;
				break;
			}
		}
		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 i;
	SelectObject(bufdc, bg);

	//背景移动
	BitBlt(mdc, 0, 0, w, 480, bufdc, 640 - w, 0, SRCCOPY);
	BitBlt(mdc, w, 0, 640 - w, 480, bufdc, 0, 0, SRCCOPY);

	//根据光标点击位置进行X位置修正
	if (nowX < x)
	{
		nowX += 10;
		if (nowX > x)
			nowX = x;
	}
	else
	{
		nowX -= 10;
		if (nowX < x)
			nowX = x;
	}

	//根据光标点击位置进行Y位置修正
	if (nowY < y)
	{
		nowY += 10;
		if (nowY > y)
			nowY = y;
	}
	else
	{
		nowY -= 10;
		if (nowY < y)
			nowY = y;
	}

	//贴飞机
	SelectObject(bufdc, ship);

	//透明处理
	BitBlt(mdc, nowX, nowY, 100, 74, bufdc, 0, 74, SRCAND);
	BitBlt(mdc, nowX, nowY, 100, 74, bufdc, 0, 0, SRCPAINT);

	SelectObject(bufdc, bullet);
	if(bcount!=0)
		for (i = 0; i < 30; i++) 		
			if (b[i].exist) 
			{
				BitBlt(mdc, b[i].x, b[i].y, 10, 10, bufdc, 0, 10, SRCAND);
				BitBlt(mdc, b[i].x, b[i].y, 10, 10, bufdc, 0, 0, SRCPAINT);
				b[i].x -= 10;
				if (b[i].x < 0) {
					bcount--;
					b[i].exist = false;
				}

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

				//背景移动
				w += 10;
				if (w == 640) 
					w = 0;
}

结果如下

猜你喜欢

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