⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game.cpp

📁 The Adventures of Subman
💻 CPP
字号:
#include <windows.h>
#include "level.h"
#include "resource.h"

#define WM_NEWGAME WM_USER + 1

#define MAP_WIDTH	100
#define MAP_HEIGHT	10

#define BMP_WIDTH	48
#define BMP_HEIGHT	48

#define MAX_ENEMIES 20

#define FLOOR		1
#define TOMATO		2
#define LETTUCE		3
#define CHEESE		4
#define MEAT		5
#define EXIT		6
#define ENEMY		7

HINSTANCE hInst;
HWND      hWndMain;
CHAR      szAppName[] = "The Adventures of Subman";
HDC       hdc;
HDC       hdcMem;
HDC       hdcBuffer;
HBITMAP   hbmBuffer;
HBITMAP   hbmGraphics;
HFONT     hFont;
HFONT     hOldFont;
int       nXOffset;
int       nYOffset;
RECT      rcClient;
CHAR      szLevelName[255];
int       nTomatoGoal;
int       nLettuceGoal;
int       nCheeseGoal;
int       nMeatGoal;
int       nNumTomato;
int       nNumLettuce;
int       nNumCheese;
int       nNumMeat;
int       nCurLevel;
BOOL      bNewGame;
int       nMap[MAP_HEIGHT][MAP_WIDTH];

struct _HERO
{
	int  nDstX;
	int  nDstY;
	int  nSrcX;
	int  nSrcY;
	int  nMatrixX;
	int  nMatrixY;
	int  nFrame;
	BOOL bAlive;
	BOOL bJumping;
	BOOL bAttacking;
	BOOL bWasAttacking;
	BOOL bLeft;

	VOID Init()
	{
		nDstX    = 0;
		nDstY    = 0;

		nMatrixX = nDstX / BMP_WIDTH;
		nMatrixY = nDstY / BMP_HEIGHT;

		nSrcX    = 1;
		nSrcY    = 148;

		nFrame   = 0;

		bAlive        = TRUE;
		bJumping      = FALSE;
		bAttacking    = FALSE;
		bWasAttacking = FALSE;
		bLeft         = FALSE;
	}

	VOID ReInit()
	{
		Init();
	}

	VOID Update()
	{
		static DWORD dwTickCount;
		static BOOL  bFirstTime = TRUE;

		if(bFirstTime)
		{
			dwTickCount = GetTickCount();

			bFirstTime  = FALSE;
		}

		if((GetTickCount() - dwTickCount) > 100)
		{
			if(bAlive)
			{
				if(GetKeyState(VK_LEFT) < 0)
				{
					if(nMap[nMatrixY][nMatrixX - 1] != FLOOR)
					{
						if(nXOffset > 0)
						{
							nMatrixX --;
							nXOffset --;
						}
						else if(nXOffset == 0 && nDstX > 0)
						{
							nDstX -= BMP_WIDTH;

							nMatrixX = nDstX / BMP_WIDTH;
							nMatrixY = nDstY / BMP_HEIGHT;
						}
					}

					bLeft = TRUE;

					nFrame ++;

					if(nFrame > 1)
						nFrame = 0;
				}
				else if(GetKeyState(VK_RIGHT) < 0)
				{
					if(nMap[nMatrixY][nMatrixX + 1] != FLOOR)
					{
						if(nDstX < (5 * BMP_WIDTH))
						{
							nDstX += BMP_WIDTH;

							nMatrixX = nDstX / BMP_WIDTH;
							nMatrixY = nDstY / BMP_HEIGHT;
						}
						else
						{
							nMatrixX ++;
							nXOffset ++;
						}
					}

					bLeft = FALSE;

					nFrame ++;

					if(nFrame > 1)
						nFrame = 0;
				}
				else
				{
					if(nFrame != 0)
						nFrame = 0;
				}

				if(GetKeyState('A') < 0)
				{
					static int nPrvX;
					static int nPrvY;

					if(nMap[nMatrixY + 1][nMatrixX] == FLOOR)
					{
						nPrvX = nMatrixX * BMP_WIDTH;
						nPrvY = nMatrixY * BMP_HEIGHT;

						bJumping = TRUE;
					}
					if((nMatrixY * BMP_HEIGHT) < (nPrvY - (3 * BMP_HEIGHT)))
					{
						bJumping = FALSE;
					}
				}
				else
				{
					if(bJumping)
						bJumping = FALSE;
				}

				if(GetKeyState('B') < 0)
				{
					if(nMap[nMatrixY + 1][nMatrixX] != FLOOR)
					{
						bAttacking = TRUE;
					}
				}

				if(bJumping)
				{
					nDstY    -= BMP_HEIGHT;
					nMatrixY --;

					if(nFrame != 2)
						nFrame = 2;
				}
				else
				{
					if(nMap[nMatrixY + 1][nMatrixX] != FLOOR)
					{
						nDstY    += BMP_HEIGHT;
						nMatrixY ++;
					}
					else
					{
						if(bAttacking)
						{
							if(!bWasAttacking)
							{
								SetTimer(hWndMain, 2, 250, (TIMERPROC)NULL);

								bWasAttacking = TRUE;
							}
						}
					}
				}

				if(bAttacking)
				{
					if(nFrame != 3)
						nFrame = 3;
				}

				if(nMap[nMatrixY][nMatrixX] == TOMATO)
				{
					nNumTomato ++;

					nMap[nMatrixY][nMatrixX] = 0;
				}
				if(nMap[nMatrixY][nMatrixX] == LETTUCE)
				{
					nNumLettuce ++;

					nMap[nMatrixY][nMatrixX] = 0;
				}
				if(nMap[nMatrixY][nMatrixX] == CHEESE)
				{
					nNumCheese ++;

					nMap[nMatrixY][nMatrixX] = 0;
				}
				if(nMap[nMatrixY][nMatrixX] == MEAT)
				{
					nNumMeat ++;

					nMap[nMatrixY][nMatrixX] = 0;
				}

				if(bLeft)
					nSrcY = 295;
				else
					nSrcY = 148;
			}
			else
			{
				if(nMap[nMatrixY + 1][nMatrixX] != FLOOR)
				{
					nDstY    += BMP_HEIGHT;
					nMatrixY ++;
				}
				else
					nFrame = 4;
			}

			nYOffset = - (nMatrixY - 3);

			nSrcX = (nFrame * BMP_WIDTH) + (nFrame + 1);

			dwTickCount = GetTickCount();
		}
	}

	VOID Draw()
	{
		hFont = CreateFont(18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
			CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Comic Sans MS");
		hOldFont = (HFONT)SelectObject(hdcBuffer, hFont);

		BitBlt(hdcBuffer, nDstX, nDstY + ((!bAlive) ? 15 : 0) + (nYOffset * BMP_HEIGHT), BMP_WIDTH, BMP_HEIGHT, hdcMem,
			nSrcX, nSrcY + (BMP_HEIGHT + 1), SRCAND);

		BitBlt(hdcBuffer, nDstX, nDstY + ((!bAlive) ? 15 : 0) + (nYOffset * BMP_HEIGHT), BMP_WIDTH, BMP_HEIGHT, hdcMem,
			nSrcX, nSrcY, SRCPAINT);

		CHAR szBuffer[255];

		wsprintf(szBuffer, "Tomato: %d out of %d\n"
						   "Lettuce: %d out of %d\n"
				           "Cheese: %d out of %d\n"
				           "Meat: %d out of %d\n", nNumTomato, nTomatoGoal, nNumLettuce, nLettuceGoal,
				 nNumCheese, nCheeseGoal, nNumMeat, nMeatGoal);

		DrawText(hdcBuffer, szBuffer, lstrlen(szBuffer), &rcClient, DT_EDITCONTROL);

		SelectObject(hdcBuffer, hOldFont);
		DeleteObject(hFont);
	}
}hero;

struct _ENEMY
{
	int   nPrvX;
	int   nPrvY;
	int   nDstX;
	int   nDstY;
	int   nSrcX;
	int   nSrcY;
	int	  nMatrixX;
	int   nMatrixY;
	int   nFrame;
	BOOL  bAlive;
	BOOL  bInit;
	BOOL  bJumping;
	DWORD dwTickCount;

	VOID Init(int nX, int nY)
	{
		nPrvX    = 0;
		nPrvY    = 0;

		nDstX    = nX;
		nDstY    = nY;

		nMatrixX = nDstX / BMP_WIDTH;
		nMatrixY = nDstY / BMP_HEIGHT;

		nSrcX    = 1;
		nSrcY    = 442;

		nFrame   = 0;

		bAlive   = TRUE;
		bInit    = TRUE;
		bJumping = FALSE;

		dwTickCount = GetTickCount();
	}

	VOID Update()
	{
		if((GetTickCount() - dwTickCount) > 1000)
		{
			if(bAlive)
			{
				if(nMap[nMatrixY + 1][nMatrixX] == FLOOR)
				{
					nPrvX = nMatrixX * BMP_WIDTH;
					nPrvY = nMatrixY * BMP_HEIGHT;

					bJumping = TRUE;
				}
				if((nMatrixY * BMP_HEIGHT) < (nPrvY - (2* BMP_HEIGHT)))
				{
					bJumping = FALSE;
				}

				if(bJumping)
				{
					nDstY    -= BMP_HEIGHT;
					nMatrixY --;
				}
				else
				{
					if(nMap[nMatrixY + 1][nMatrixX] != FLOOR)
					{
						nDstY    += BMP_HEIGHT;
						nMatrixY ++;
					}
				}
			}
			else
			{
				if(nFrame < 2)
					nFrame ++;
			}

			dwTickCount = GetTickCount();
		}

		if(hero.nMatrixX == nMatrixX && hero.nMatrixY == nMatrixY)
		{
			if(hero.bAttacking)
			{
				if(bAlive)
				{
					nFrame = 1;

					bAlive = FALSE;
				}
			}
			else
			{
				hero.bAlive = FALSE;
			}
		}

		nSrcX = (nFrame * BMP_WIDTH) + (nFrame + 1);
	}

	VOID Draw()
	{
		BitBlt(hdcBuffer, nDstX - (nXOffset * BMP_WIDTH), nDstY + (nYOffset * BMP_HEIGHT), 
			BMP_WIDTH, BMP_HEIGHT, hdcMem, nSrcX, nSrcY + (BMP_HEIGHT + 1), SRCAND);

		BitBlt(hdcBuffer, nDstX - (nXOffset * BMP_WIDTH), nDstY + (nYOffset * BMP_HEIGHT), 
			BMP_WIDTH, BMP_HEIGHT, hdcMem, nSrcX, nSrcY, SRCPAINT);
	}
}enemies[MAX_ENEMIES];

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam,
							 LPARAM lParam)
{
	PAINTSTRUCT ps;

	switch(Msg)
	{
	case WM_PAINT:
		{
			hdc = BeginPaint(hWnd, &ps);
			
			if(!bNewGame)
			{
				FillRect(hdcBuffer, &rcClient, (HBRUSH)GetStockObject(WHITE_BRUSH));

				SelectObject(hdcMem, hbmGraphics);

				for(int nY = 0; nY < MAP_HEIGHT; nY ++)
				{
					for(int nX = 0; nX < MAP_WIDTH; nX ++)
					{
						int nDstX = (nX * BMP_WIDTH)  - (nXOffset * BMP_WIDTH);
						int nDstY = (nY * BMP_HEIGHT) + (nYOffset * BMP_HEIGHT);

						switch(nMap[nY][nX])
						{
						case FLOOR:
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 197, 1,
								SRCCOPY);
							break;
						case TOMATO:
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 1, 50,
								SRCAND);
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 1, 1,
								SRCPAINT);
							break;
						case LETTUCE:
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 50, 50,
								SRCAND);
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 50, 1,
								SRCPAINT);
							break;
						case CHEESE:
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 99, 50,
								SRCAND);
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 99, 1,
								SRCPAINT);
							break;
						case MEAT:
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 148, 50,
								SRCAND);
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 148, 1,
								SRCPAINT);
							break;
						case EXIT:
							BitBlt(hdcBuffer, nDstX, nDstY, BMP_WIDTH, BMP_HEIGHT, hdcMem, 246, 1,
								SRCCOPY);
							break;
						}
					}
				}

				for(int i = 0; i < MAX_ENEMIES; i ++)
				{
					if(enemies[i].bInit)
						enemies[i].Draw();
				}

				hero.Draw();
			}

			BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcBuffer, 0, 0,
				SRCCOPY);

			EndPaint(hWnd, &ps);
		}
		break;
	case WM_CREATE:
		GetClientRect(hWnd, &rcClient);

		hdc       = GetDC(hWnd);
		hdcMem    = CreateCompatibleDC((HDC)NULL);
		hdcBuffer = CreateCompatibleDC(hdc);
		hbmBuffer = CreateCompatibleBitmap(hdc, rcClient.right,
			rcClient.bottom);

		hbmGraphics = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_GRAPHICS));

		SelectObject(hdcBuffer, hbmBuffer);

		FillRect(hdcBuffer, &rcClient, (HBRUSH)GetStockObject(WHITE_BRUSH));

		SetTextColor(hdcBuffer, RGB(0, 0, 255));

		SetBkMode(hdcBuffer, TRANSPARENT);

		hero.Init();

		nCurLevel = 1;

		bNewGame  = TRUE;

		ReleaseDC(hWnd, hdc);

		SetTimer(hWnd, 1, 1, (TIMERPROC)NULL);
		break;
	case WM_NEWGAME:
		{
			CHAR szBuffer[255];

			hdc = GetDC(hWnd);

			hFont = CreateFont(24, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
				CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Comic Sans MS");
			hOldFont = (HFONT)SelectObject(hdcBuffer, hFont);

			DrawText(hdcBuffer, szLevelName, lstrlen(szLevelName), &rcClient,
				DT_SINGLELINE | DT_CENTER | DT_VCENTER);

			switch(nCurLevel)
			{
			case 1:
				lstrcpy(szBuffer, "Collect 2 Tomato\n");
				lstrcat(szBuffer, "Collect 2 Lettuce\n");
				lstrcat(szBuffer, "Collect 2 Cheese\n");
				lstrcat(szBuffer, "Collect 2 Meat\n");
				break;
			}

			DrawText(hdcBuffer, szBuffer, lstrlen(szBuffer), &rcClient,
				DT_EDITCONTROL | DT_CENTER | DT_VCENTER);

			BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcBuffer, 0, 0,
				SRCCOPY);

			ReleaseDC(hWnd, hdc);

			SelectObject(hdcBuffer, hOldFont);
			DeleteObject(hFont);

			Sleep(1000);
		}
		break;
	case WM_TIMER:
		switch(wParam)
		{
		case 1:
			{
				if(bNewGame)
				{
					int nCurEnemy = 0;

					switch(nCurLevel)
					{
					case 1:
						lstrcpy(szLevelName, "Easy As Sunday Morning");
						break;
					}

					for(int nY = 0; nY < MAP_HEIGHT; nY ++)
					{
						for(int nX = 0; nX < MAP_WIDTH; nX ++)
						{
							nMap[nY][nX] = nLevel[((nCurLevel - 1) * MAP_HEIGHT) + nY][nX];

							if(nMap[nY][nX] == ENEMY)
							{
								int nDstX = nX * BMP_WIDTH;
								int nDstY = nY * BMP_HEIGHT;

								enemies[nCurEnemy].Init(nDstX, nDstY);

								nCurEnemy ++;
							}
						}
					}

					SendMessage(hWnd, WM_NEWGAME, (WPARAM)0, (LPARAM)0);

					bNewGame = FALSE;
				}

				for(int i = 0; i < MAX_ENEMIES; i ++)
				{
					if(enemies[i].bAlive)
						enemies[i].Update();
				}

				hero.Update();

				InvalidateRect(hWnd, (CONST RECT*)NULL, FALSE);
			}
			break;
		case 2:
			hero.bAttacking    = FALSE;
			hero.bWasAttacking = FALSE;

			KillTimer(hWnd, 2);
			break;
		}
		break;
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		KillTimer(hWnd, 1);

		DeleteDC(hdc);
		DeleteDC(hdcMem);
		DeleteDC(hdcBuffer);

		DeleteObject(hbmBuffer);
		DeleteObject(hbmGraphics);

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

	return NULL;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nShowCmd)
{
	HWND     hWnd;
	WNDCLASS wc;
	MSG      msg;

	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.hCursor       = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
	wc.hIcon         = LoadIcon((HINSTANCE)NULL, IDI_APPLICATION);
	wc.hInstance     = hInstance;
	wc.lpfnWndProc   = MainWndProc;
	wc.lpszClassName = szAppName;
	wc.lpszMenuName  = (LPCTSTR)NULL;
	wc.style	     = 0;

	if(!RegisterClass(&wc))
	{
		return NULL;
	}

	hInst = hInstance;

	hWnd  = CreateWindow(szAppName, szAppName, WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND)NULL, (HMENU)NULL,
		hInstance, (LPVOID)NULL);

	if(!hWnd)
	{
		return NULL;
	}

	hWndMain = hWnd;

	ShowWindow(hWnd, nShowCmd);
	UpdateWindow(hWnd);

	while(GetMessage(&msg, (HWND)NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int)msg.wParam;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -