一派护法 十九级 |
【Invader.cpp】 #include <stdio.h> #include <Windows.h> #include "Invader.h"
static unsigned char charset[16 * 8] = { /* invader(0) */ 0x00, 0x00, 0x00, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x20, 0x3f, 0x00,
/* invader(1) */ 0x00, 0x0f, 0x7f, 0xff, 0xcf, 0xcf, 0xcf, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x00,
/* invader(2) */ 0x00, 0xf0, 0xfe, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0x07, 0xff, 0xff, 0x03, 0x03, 0x03, 0x00,
/* invader(3) */ 0x00, 0x00, 0x00, 0xc2, 0xfa, 0xfa, 0xfa, 0xfe, 0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x04, 0xfc, 0x00,
/* fighter(0) */ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x43, 0x47, 0x4f, 0x5f, 0x7f, 0x7f, 0x00,
/* fighter(1) */ 0x18, 0x7e, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0x00,
/* fighter(2) */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc2, 0xe2, 0xf2, 0xfa, 0xfe, 0xfe, 0x00,
/* laser */ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00 }; /* invader:"abcd", fighter:"efg", laser:"h" */
HWND hWnd; struct INVADER { int fighter_x; // 自机的坐标 int laser_x, laser_y; // 等离子炮弹的坐标 int invaders_x, invaders_y; // 外星人群的坐标 int invaders_direction; // 外星人群的移动方向 int laserwait; // 等离子炮弹的剩余充电时间 int movewait; // 为0时外星人群前进一步 int movewait0; // movewait的初始值(消灭30只敌人后减少) int invaders_line; // 外星人群的行数 int score; // 当前得分 int high; // 最高得分 int point; // 得分的增加量(奖金的单价) char invaders_str[32 * 6]; // 将外星人群的状态显示为字符串的变量 int flags; // 游戏状态 } invader;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // 窗口的背景为黑色 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wcex.hInstance = hInstance; wcex.lpfnWndProc = WndProc; wcex.lpszClassName = "WC_Invader"; wcex.lpszMenuName = NULL; wcex.style = NULL; RegisterClassEx(&wcex);
// 根据客户区大小计算窗口大小 DWORD style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; RECT rect; rect.left = rect.top = 0; rect.right = 323; rect.bottom = 227; AdjustWindowRect(&rect, style, NULL);
HWND hWnd = CreateWindow(wcex.lpszClassName, "Invader", style, CW_USEDEFAULT, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL); if (!hWnd) return 1; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: ::hWnd = hWnd; restart(); break; case WM_DESTROY: KillTimer(hWnd, IDT_TIMER1); PostQuitMessage(0); break; case WM_KEYDOWN: keyboard_handler(wParam); break; case WM_PAINT: wnd_paint(); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return FALSE; }
void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT iTimerID, DWORD dwTime) { if (invader.laserwait != 0) invader.laserwait--; // 等离子炮的充电时间保证了每次只能发射一粒炮弹 invaders_move(); laser_move(); }
void gameover(void) { KillTimer(hWnd, IDT_TIMER1); invader.flags |= F_GAMEOVER; update_gameover(); }
void invaders_move(void) { if (invader.movewait != 0) { invader.movewait--; return; } invader.movewait = invader.movewait0; if (invader.invaders_x + invader.invaders_direction > 14 || invader.invaders_x + invader.invaders_direction < 0) { if (invader.invaders_y + invader.invaders_line == 13) { gameover(); return; } invader.invaders_direction = -invader.invaders_direction; invader.invaders_y++; } else invader.invaders_x += invader.invaders_direction; update_invaders(); }
void keyboard_handler(WPARAM wParam) { switch (wParam) { case 0x0d: // enter if (invader.flags & F_GAMEOVER) { invader.flags &= ~F_GAMEOVER; restart(); update(); } break; case 0x20: case 0x26: // space if (invader.laserwait == 0) { invader.laserwait = 15; invader.laser_x = invader.fighter_x + 1; invader.laser_y = 13; } break; case 0x25: case 0x64: // left if (invader.fighter_x > 0) { invader.fighter_x--; update_fighter(); } break; case 0x27: case 0x66: // right if (invader.fighter_x < 37) { invader.fighter_x++; update_fighter(); } } }
void laser_move(void) { if (invader.laser_y <= 0) return; // 如果invader.laser_y已经降至0, 则不执行任何操作
invader.laser_y--; update_laser(); if (invader.laser_y == 0) { // 当invader.laser_y降至0的瞬间 invader.point -= 10; if (invader.point <= 0) invader.point = 1; } if (invader.invaders_x < invader.laser_x && invader.laser_x < invader.invaders_x + 25 && invader.invaders_y <= invader.laser_y && invader.laser_y < invader.invaders_y + invader.invaders_line) { int pos = (invader.laser_y - invader.invaders_y) * 32 + invader.laser_x - invader.invaders_x; if (invader.invaders_str[pos] != ' ') { // 击中 invader.score += invader.point; invader.point++; if (invader.high < invader.score) invader.high = invader.score; update_score(); while (pos >= 0 && invader.invaders_str[pos] != ' ') pos--; // pos的最小值为-1 memset(&invader.invaders_str[pos + 1], ' ', 4); update_invader_hit(); while (invader.invaders_line > 0) { for (pos = (invader.invaders_line - 1) * 32; invader.invaders_str[pos] != '\0'; pos++) { if (invader.invaders_str[pos] != ' ') { // 有存活的情况下 invader.laser_y = 0; return; } } invader.invaders_line--; }
// 全部消灭的情况下 invader.movewait0 -= invader.movewait0 / 3; // 加速 next_group(); update_invaders(); } } }
void next_group(void) { static char invader_str0[32] = " abcd abcd abcd abcd abcd "; invader.invaders_x = 7; invader.invaders_y = 1; invader.invaders_line = 6; invader.laser_y = 0; invader.movewait = invader.movewait0; invader.invaders_direction = 1;
int i, j; for (i = 0; i < invader.invaders_line; i++) { for (j = 0; j < 27; j++) invader.invaders_str[i * 32 + j] = invader_str0[j]; } }
void putimg(HDC hdc, RECT *rcPaint, int x, int y, COLORREF color, LPCSTR imgstr) { x *= 8; y *= 16;
int i, j; int x0, y0; while (*imgstr != '\0') { if (x > rcPaint->right) return; if (*imgstr >= 'a' && *imgstr <= 'h') { int pos = 16 * (*imgstr - 'a'); for (i = 0; i < 16; i++) { if ((y0 = y + i) > rcPaint->bottom) break; if (y0 < rcPaint->top) continue; for (j = 0; j < 8; j++) { if ((x0 = x + j) > rcPaint->right) break; if (x0 < rcPaint->left) continue; if (charset[pos + i] & _BV(7 - j)) SetPixel(hdc, x0, y0, color); } } } imgstr++; x += 8; } }
void putstr(HDC hdc, int x, int y, LPCSTR str) { TextOut(hdc, x * 8, y * 16, str, strlen(str)); }
void restart(void) { invader.score = 0; invader.point = 1; invader.movewait0 = 20; invader.fighter_x = 18; next_group(); SetTimer(hWnd, IDT_TIMER1, 40, TimerProc); }
// 更新整个游戏画面 void update(void) { RECT rect; GetClientRect(hWnd, &rect); InvalidateRect(hWnd, &rect, TRUE); }
// 更新自机部分的画面 void update_fighter(void) { // 擦除屏幕上y>=208的区域并重新绘制 RECT rect; GetClientRect(hWnd, &rect); rect.top = 208; InvalidateRect(hWnd, &rect, TRUE); }
// 更新GAME OVER文字 void update_gameover(void) { RECT rect; rect.left = 120; rect.top = 96; rect.right = 264; rect.bottom = 112; InvalidateRect(hWnd, &rect, TRUE); }
// 更新击中的外星人那一行画面 void update_invader_hit(void) { RECT rect; GetClientRect(hWnd, &rect); rect.top = invader.laser_y * 16; rect.bottom = rect.top + 16; InvalidateRect(hWnd, &rect, FALSE); }
// 更新显示全部外星人的那部分画面 void update_invaders(void) { RECT rect; GetClientRect(hWnd, &rect); rect.top = 16; rect.bottom = 207; InvalidateRect(hWnd, &rect, FALSE); }
// 更新等离子炮弹那部分画面 void update_laser(void) { RECT rect; rect.left = invader.laser_x * 8; rect.top = invader.laser_y * 16; rect.right = rect.left + 8; rect.bottom = rect.top + 32; InvalidateRect(hWnd, &rect, FALSE); }
// 更新显示得分信息的那部分画面 void update_score(void) { RECT rect; GetClientRect(hWnd, &rect); rect.bottom = 16; InvalidateRect(hWnd, &rect, FALSE); }
// 窗口绘制 void wnd_paint(void) { RECT rect; GetClientRect(hWnd, &rect); PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); HDC hdcMem = CreateCompatibleDC(hdc); HBITMAP hbmpMem = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top); SelectObject(hdcMem, hbmpMem); // 绘制分数 SetBkColor(hdcMem, COL_BLACK); if (ps.rcPaint.top <= 16) { char str[15]; SetTextColor(hdcMem, COL_WHITE); sprintf_s(str, "HIGH:%08d", invader.high); putstr(hdcMem, 22, 0, str); sprintf_s(str, "SCORE:%08d", invader.score); putstr(hdcMem, 4, 0, str); }
// 绘制外星人 int i; for (i = 0; i < invader.invaders_line; i++) { putimg(hdcMem, &ps.rcPaint, invader.invaders_x, invader.invaders_y + i, COL_GREEN, invader.invaders_str + i * 32); }
putimg(hdcMem, &ps.rcPaint, invader.fighter_x, 13, COL_CYAN, "efg"); // 绘制自机 if (invader.laser_y > 0) // 确保炮弹不会出现在显示分数的那一栏 putimg(hdcMem, &ps.rcPaint, invader.laser_x, invader.laser_y, COL_YELLOW, "h"); // 绘制炮弹
// 绘制GAME OVER字样 if (invader.flags & F_GAMEOVER) { SetTextColor(hdcMem, COL_RED); putstr(hdcMem, 15, 6, "GAME OVER"); }
BitBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdcMem, rect.left, rect.top, SRCCOPY); EndPaint(hWnd, &ps); DeleteDC(hdcMem); DeleteObject(hbmpMem); }
|