📄 game.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 + -