目次
- ゲーム紹介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 を呼び出してそれを消去します。小道具は大きな飛行機をクリアすると生成され、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);