目录
- 游戏介绍 1
- 游戏流程 1
- 界面设计 2
- 概要设计 2
4.1 系统架构 2
4.2 核心代码流程 2 - 总结与感悟 3
- 参考资料 3
4.2核心代码流程
游戏逻辑的主要部分,核心代码之所在,Run_Timer函数的流程如下所示。
流程开始:由WinProc调用。
S0:更新计时器全局变量。
S1:遍历所有敌机,调用HitHero判断是否与我机相撞(如相撞,标记敌机)。
S2:遍历所有子弹和所有飞机,调用Hit判断是否击中(如击中,标记子弹和飞机)。
S3:遍历所有道具,调用GetToy判断是否被我机拾获(如拾获,标记道具,产生道具效果,设置相应全局变量)。
S4:判断当前分数和关卡,如果需要,升级关卡。
S5:判断计时器全局变量的值,如符合频率要求,创建一架新敌机。
S6:遍历所有敌机,产生位移。
S7:判断计时器全局变量的值,如符合频率要求,以一定概率随机使敌机产生新的子弹。
S8:遍历所有敌机,若飞出屏幕,调用DestroyPlane清除。
S9:遍历所有子弹,产生位移。
S10:遍历所有道具,产生位移。
S11:判断计时器全局变量的值,如符合频率要求,使我机产生新的子弹。根据全局变量记录的道具信息产生不同子弹,更新道具冷却时间全局变量。
S12:加分。
S13:清除无效的飞机。遍历所有敌机,若发现被标记,调用DestroyPlane清除之。在大飞机被清除时产生道具,在Hero快没血的时候以更大的概率产生 toyBLD。
S14:清除无效的子弹。遍历所有子弹,若发现被标记,调用DestoryBullet清除之。
S15:清除无效的道具。遍历所有道具,若发现被标记,调用DestoryToy清除之。
S16:动画进帧。
流程结束,控制流交还WinProc以绘图。
#include "DigitPlane.h"
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wcex;
HWND hWnd;
MSG msg;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Mega Plane"),
MB_OK);
return 1;
}
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create,~WS_THICKFRAME fixed window size
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// WNDWIDTH, WNDHEIGHT: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW, //& ~WS_THICKFRAME,
//CW_USEDEFAULT, CW_USEDEFAULT,
20,20,
O_WNDWIDTH + WNDWIDTH_PLUS, O_WNDHEIGHT + WNDHEIGHT_PLUS,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Mega Plane"),
MB_OK);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
BITMAP bmp;
POINT ptMouse;
int i;
switch (message)
{
case WM_CREATE:
//加载位图资源
m_hBackgroundBmp = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance,
MAKEINTRESOURCE(IDB_BACKGROUND));
m_hHeroBmp = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance,
MAKEINTRESOURCE(IDB_HERO));
m_hHeroBulletBmp = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance,
MAKEINTRESOURCE(IDB_HERO_BULLET));
for (i = 0; i < ENEMY_TYPE_NUM; i++)
{
m_hEnemyBmp[i] = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance,
MAKEINTRESOURCE(m_enemyBmpNames[i]));
}
m_hGameStatusBmp = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance,
MAKEINTRESOURCE(IDB_GAME_STATUS));
m_hToysBmp = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance,
MAKEINTRESOURCE(IDB_TOYS));
Initialize_Game();
m_gameStatus.isPaused = FALSE;
m_gameStatus.isStarting = TRUE;
{
//位图相关
GetObject(m_hGameStatusBmp, sizeof(BITMAP), &bmp);
m_gameStatus.size.cx = bmp.bmWidth;
m_gameStatus.size.cy = bmp.bmHeight / 2;
m_gameStatus.hBmp = m_hGameStatusBmp;
}
srand((unsigned int)time(NULL));
timer_i = 0;
//开始背景音乐
PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL),SND_LOOP|SND_ASYNC|SND_RESOURCE);
break;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//绘制
Render(hdc);
EndPaint(hWnd, &ps);
break;
case WM_KEYUP:
switch (wParam)
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
MOVE_HERO = 0;
break;
}
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
MOVE_HERO = wParam;
break;
case VK_SPACE:
if(m_Planes[0].status == 0)
{
//Restart_Game
Initialize_Game();
}
else
{
if(m_gameStatus.isStarting)
{
SetTimer(hWnd, TIMER, 50, NULL);
m_gameStatus.isStarting = FALSE;
InvalidateRect(hWnd, NULL, FALSE);
}
else
Pause_Game(hWnd);
}
break;
case 'B':
m_Toys[Toy_Count] = CreateToy(toyBLD);
break;
case 'D':
m_Toys[Toy_Count] = CreateToy(toyDBL);
break;
case 'C':
m_Toys[Toy_Count] = CreateToy(toyCLS);
break;
case 'R':
m_Toys[Toy_Count] = CreateToy(toyRAD);
break;
case 'S':
m_Toys[Toy_Count] = CreateToy(toySUB);
break;
case 'M'://狂躁模式,各种子弹特效全开
DBLBullet = TRUE;
RADBullet = TRUE;
SUBBullet = TRUE;
break;
default:
break;
}
break;
case WM_LBUTTONDOWN:
ptMouse.x = LOWORD(lParam);
ptMouse.y = HIWORD(lParam);