【Windows.net】——PacMan小游戏

本文分享了一个基于Windows平台的吃豆人游戏实现代码,使用C++进行开发,并介绍了游戏的基本功能,包括开始游戏、自动模式、暂停与重新开始等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

距离上一篇博客已经很长时间了,升了大二,学了更多的东西,眼界更开阔了,回顾以前的寥寥几篇博客,相当的相当的矫情,总之现在还是坚持在学软件工程。这学期学了数据结构和Windows编程(C++可视化程序设计),很受启发,前段时间Windows要求完成一个吃豆人的小游戏,我贴一下自己的源代码。希望对正在学Windows的同学有用

 

//PacMan.cpp
#include<iostream>
#include "windows.h"
#include"resource.h"
#include<stdlib.h>
#include<time.h>
#include"atlstr.h"
#include"CString"
#include "mmsystem.h"//导入声音头文件
#pragma comment(lib,"winmm.lib")
using namespace std;
#define Max 100
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
	WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX WndClass;
	HWND hWnd;
	MSG msg;
	WndClass.cbSize = sizeof(WNDCLASSEX);
	WndClass.style = 0;
	WndClass.lpfnWndProc = WndProc;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
	WndClass.lpszClassName = "WindowClass";
	WndClass.hIconSm = LoadIcon(WndClass.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

	if (!RegisterClassEx(&WndClass))
	{
		MessageBox(NULL, "窗口类注册失败!", "窗口注册", NULL);
		return 1;
	}

	hWnd = CreateWindow(
		"WindowClass",
		"PacMan",
		WS_OVERLAPPEDWINDOW,
		0, 0,
		1000, 650,
		NULL,
		NULL,
		hInstance,
		NULL
	);
	if (!hWnd)
	{
		MessageBox(NULL,"窗口创建失败!", "创建窗口 ", NULL);
		return 1;
	}
	ShowWindow(hWnd, nCmdShow);
	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)
{
	HDC hdc;
	PAINTSTRUCT ps;
	HPEN hP;
	HBRUSH hB;
	TEXTMETRIC tm;
	int t[Max];
	CString d[Max];
	for (int m = 0; m < Max; m++)
	{
		t[m] = m;
	}
	for (int m = 0; m < Max; m++)
	{
		d[m].Format("%d", t[m]);
	}
	static int score = 0;
	static int a[80], b[80];
	static int x3, y3;
	static BOOL nRightKeyDown = FALSE, nLeftKeyDown = FALSE,
		        nUpKeyDown =    FALSE, nDownKeyDown = FALSE;
	static BOOL Begin     = FALSE;
	static BOOL Pause     = FALSE;
	static BOOL Continue  = FALSE;
	static BOOL Auto      = FALSE;
	static BOOL Opp       = FALSE;
	static int x1 = 0, x2 = 40, y1 = 0, y2 = 40;
	static int ox1 = 900, oy1 = 520, ox2 = 930, oy2 = 550;
	switch (message)
	{
	case WM_COMMAND:
		switch (wParam)//(LOWORD(wParam))
		{
		case IDM_BEGIN:
			Begin = TRUE;
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		case IDM_PAUSE:
			Pause = TRUE;
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		case IDM_EXIT:
			SendMessage(hwnd, WM_DESTROY, 0, 0);
			break;
		case IDM_CONTINUE:
			Pause = FALSE;
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		case IDM_RBEGIN:
			Pause = FALSE;
			Begin = TRUE;
			x1 = 0, x2 = 50, y1 = 0, y2 = 50;
			srand(time(NULL));
			for (int i = 0; i < 40; i++)
			{
				a[i] = rand() % 760;
				b[i] = rand() % 570;
			}
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		case ID_40007:
			break;
		case ID_40008:
			ShellExecute(NULL, NULL, _T("https://msdn.microsoft.com/zh-cn"), NULL, NULL, SW_SHOWNORMAL);
			break;
		case IDM_AUTO:
			Auto = TRUE;
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		}
		break;
	case WM_CREATE:
		srand(time(NULL));
		for (int i = 0; i < 80; i++)
		{
			a[i] = rand() % 960;
			b[i] = rand() % 770;
		}
		SetTimer(hwnd, 1, 700, NULL);
		break;
	case WM_PAINT:
		if (Begin == TRUE && Auto == FALSE)
		{

			hdc = BeginPaint(hwnd, &ps);
			hP = (HPEN)GetStockObject(BLACK_PEN);
			hB = CreateSolidBrush(RGB(127, 255, 0));
			SelectObject(hdc, hP);
			SelectObject(hdc, hB);
			Ellipse(hdc, ox1, oy1, ox2, oy2);
			GetTextMetrics(hdc, &tm);
			SetTextColor(hdc, RGB(0, 0, 0));
			TextOut(hdc, ox1-7, oy1-17, "Enemy", 5);

			hP = (HPEN)GetStockObject(BLACK_PEN);
			hB = CreateSolidBrush(RGB(160, 42, 42));
			SelectObject(hdc, hP);
			SelectObject(hdc, hB);
			Ellipse(hdc, x1, y1, x2, y2);
			for (int m = 0; m < 40; m++)
			{
				hB = CreateSolidBrush(RGB(255, 180, 185));
				SelectObject(hdc, hB);
				Ellipse(hdc, a[m], b[m], a[m] + 10, b[m] + 10);
			}
			GetTextMetrics(hdc, &tm);
			SetTextColor(hdc, RGB(0, 0, 0));
			TextOut(hdc, 1020, 30, "Score : ", 8);
			if (score <= 9)
				TextOut(hdc, 1100, 30, d[score], 1);
			else
				TextOut(hdc, 1100, 30, d[score], 2);
			for (int j = 0; j < 40; j++)
			{
				if (((x1 - a[j] + 10)*(x1 - a[j] + 10) +
					(y1 - b[j] + 10)*(y1 - b[j] + 10)) <= 680)
				{

					score++;
					PlaySound(MAKEINTRESOURCE(IDR_EATING), (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), SND_RESOURCE | SND_ASYNC);//MAKEINTRESOURSE函数是根据资源的id号调用资源
					a[j] = 0, b[j] = 0;
					InvalidateRect(hwnd, NULL, TRUE);
					a[j] = rand() % 960;
					b[j] = rand() % 770;
					Ellipse(hdc, a[j], b[j], a[j] + 10, b[j] + 10);
				}
			}
			if (((x1 - ox1 + 15)*(x1 - ox2 + 15) +(y1 - oy1 + 15)*(y1 - oy2 + 15)) <= 680)
			{
				PlaySound(MAKEINTRESOURCE(IDR_GAMEOVER), (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), SND_RESOURCE | SND_ASYNC);
			}
			if (Opp == true)
			{

				//Ellipse(hdc, ox1, oy1, ox2, oy2);
				//srand(time(NULL));
				int direction =(int)(3 * rand() / (RAND_MAX + 1.0)) + 1;// rand() * 3 + 1; 生成1——4之间的随机数
				if (direction == 1&&ox1<950 && oy1<=760 && ox2<950 && oy2 <= 760)
				{
					oy1 = oy1 + 30;
					oy2 = oy2 + 30;
				}
				else
					if (direction == 2 && ox1<950 && oy1 <= 760 && ox2<950 && oy2 <= 760)
					{
						oy1 = oy1 - 30;
						oy2 = oy2 - 30;
					}
					else
						if (direction == 3 && ox1<950 && oy1 <= 760 && ox2<950 && oy2 <= 760)
						{
							ox1 = ox1 - 30;
							ox2 = ox2 - 30;
						}
						else
						{
							ox1 = ox1 + 30;
							ox2 = ox2 + 30;
						}
				Opp = false;
			}
		}
		else if(Auto==true)
		{

			hdc = BeginPaint(hwnd, &ps);
			hP = (HPEN)GetStockObject(BLACK_PEN);
			hB = CreateSolidBrush(RGB(25, 25, 112));//MidnightBlue
			SelectObject(hdc, hP);
			SelectObject(hdc, hB);
			Ellipse(hdc, x1, y1, x2, y2);
			GetTextMetrics(hdc, &tm);
			SetTextColor(hdc, RGB(255, 0, 0));
			TextOut(hdc, x1-9, y1-17, "automatic", 9);
			TextOut(hdc, 820, 30, "You are under automatic mode, we won't count your score!", 56);
			TextOut(hdc, 820, 50, "This mode is just for show", 26);

			for (int m = 0; m < 80; m++)
			{
				hB = CreateSolidBrush(RGB(100, 149, 237));//CornflowerBlue
				SelectObject(hdc, hB);
				Ellipse(hdc, a[m], b[m], a[m] + 10, b[m] + 10);
			}
			for (int j = 0; j < 80; j++)
			{
				if (((x1 - a[j] + 10)*(x1 - a[j] + 10) +
					(y1 - b[j] + 10)*(y1 - b[j] + 10)) <= 680)
				{

					score++;
					PlaySound(MAKEINTRESOURCE(IDR_EATING), (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), SND_RESOURCE | SND_ASYNC);
					a[j] = 0, b[j] = 0;
					InvalidateRect(hwnd, NULL, TRUE);
					a[j] = rand() % 960;
					b[j] = rand() % 770;
					Ellipse(hdc, a[j], b[j], a[j] + 10, b[j] + 10);
				}
			}
				int direction2 = (int)(3 * rand() / (RAND_MAX + 1.0)) + 1;//生成1——4之间的随机数
				if (direction2 == 1&&ox1<950 && oy1<=760 && ox2<950 && oy2 <= 760)
				{
					y1 = y1 + 30;
					y2 = y2 + 30;
				}
				else
					if (direction2 == 2&&ox1<950 && oy1<=760 && ox2<950 && oy2 <= 760)
					{
						y1 = y1 - 30;
						y2 = y2 - 30;
					}
					else
						if (direction2 == 3&&ox1<950 && oy1<=760 && ox2<950 && oy2 <= 760)
						{
							x1 = x1 - 30;
							x2 = x2 - 30;
						}
						else
						{
							x1 = x1 + 30;
							x2 = x2 + 30;
						}
		}
		DeleteObject(hB);
		DeleteObject(hP);
		EndPaint(hwnd, &ps);
		break;
	case WM_TIMER:
		Opp = true;
		InvalidateRect(hwnd, NULL, TRUE);
		break;
	case WM_KEYDOWN:
	{
		switch (wParam)
		{
		case VK_UP:
			if ((y2 >= 50 && Pause == FALSE) || Continue == TRUE)
			{
				nUpKeyDown = TRUE;
				x1 = x1;
				x2 = x2;
				y1 = y1 - 10;
				y2 = y2 - 10;

			}
			else if ((y2< 50 || Pause == TRUE) && Continue == FALSE)
			{
				x1 = x1;
				x2 = x2;
				y1 = y1;
				y2 = y2;
				nUpKeyDown = FALSE;
			}
			//Opp = false;
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		case VK_DOWN:
			if (y1 <= 760 && Pause == FALSE)
			{
				nDownKeyDown = TRUE;
				x1 = x1;
				x2 = x2;
				y1 = y1 + 10;
				y2 = y2 + 10;
			}
			else if (y1 > 760 || Pause == TRUE)
			{
				nDownKeyDown = FALSE;
				x1 = x1;
				x2 = x2;
				y1 = y1;
				y2 = y2;
			}
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		case VK_LEFT:
			if (x2 >= 50 && Pause == FALSE)
			{
				nLeftKeyDown = TRUE;
				x1 = x1 - 10;
				x2 = x2 - 10;
				y1 = y1;
				y2 = y2;
			}
			else if (x2 < 50 || Pause == TRUE)
			{
				nLeftKeyDown = FALSE;
				x1 = x1;
				x2 = x2;
				y1 = y1;
				y2 = y2;
			}
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		case VK_RIGHT:
			if (x1 <= 950 && Pause == FALSE)
			{
				nRightKeyDown = TRUE;
				x1 = x1 + 10;
				x2 = x2 + 10;
				y1 = y1;
				y2 = y2;
			}
			else if (x1 > 950 || Pause == TRUE)
			{
				nRightKeyDown = FALSE;
				x1 = x1;
				x2 = x2;
				y1 = y1;
				y2 = y2;
			}
			//Opp = false;
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		}
	}
	break;
	case WM_DESTROY:
		PostQuitMessage(0);
		KillTimer(hwnd, 1);
		break;
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
		break;
	}
	return 0;
}
//resourse.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 PacMan.rc 使用
//
#define IDR_MENU1                       101
#define IDR_EATING                      104
#define IDR_GAMEOVER                    105
#define ID_WENJIA_XFYH                  40001
#define ID_WENJIA_GHG                   40002
#define IDM_BEGIN                       40005
#define IDM_EXIT                        40006
#define ID_40007                        40007
#define ID_40008                        40008
#define ID_40009                        40009
#define IDM_PAUSE                       40010
#define ID_40011                        40011
#define IDM_CONTINUE                    40012
#define ID_40013                        40013
#define IDM_RBEGIN                      40014
#define IDM_AUTO                        40015
#define ID_DIALOG                       40016

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        107
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
//PacMan.rc
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""winres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MENU1 MENUEX
BEGIN
    POPUP "游戏",                             65535,MFT_STRING,MFS_ENABLED
    BEGIN
        MENUITEM "开始",                          IDM_BEGIN,MFT_STRING | MFT_RIGHTJUSTIFY,MFS_ENABLED

        MENUITEM "退出",                          IDM_EXIT,MFT_STRING,MFS_ENABLED

    END

    MENUITEM "技术支持",                        ID_40008,MFT_STRING,MFS_ENABLED
    MENUITEM "自动模式",                        IDM_AUTO,MFT_STRING,MFS_ENABLED
END
/////////////////////////////////////////////////////////////////////////////
//
// WAVE
//

IDR_EATING                 WAVE                    "wave4.bin"

IDR_GAMEOVER               WAVE                    "wave1.bin"

#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED


在过程中,我遇到了一些问题:

 

1.添加wave文件时没有找到正确的添加方法,所以只能从网上找到了音频源代码,直接打开了C++编辑视图添加了进去;

2.时间原因,没有能在交作业之前添加更多关于敌人Opp的扩展功能,比如PacMan碰到Opp之后可以弹出一个对话框表示“Game Over”,且PacMan消失等;

3.如何添加更多的资源文件形成一个完整的游戏。

后续会继续完善这个作业
 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值