/* ゲームスレッドスクロール 2004/ 1/28 宍戸 輝光 */ #include #include #include #include #include #pragma comment(lib, "winmm.lib") HINSTANCE g_hInstance; HWND g_hwMain; HANDLE g_hGameThread; DWORD g_dwGameThreadID; /* スクロールビットマップ用変数 */ BITMAPINFO g_biScroll; LPDWORD g_lppxScroll; HBITMAP g_hbmpScrollOld, g_hbmpScroll; HDC g_hdcScroll; /* 表示用ビットマップ用変数 */ BITMAPINFO g_biDisp; LPDWORD g_lppxDisp; HBITMAP g_hbmpDispOld, g_hbmpDisp; HDC g_hdcDisp; /* マップチップ用変数 */ BITMAPINFO g_biMapTips; LPDWORD g_lppxMapTips, g_alppxMapTip[4]; /* スクロール量設定変数 */ DWORD g_iDdy = -1; /* スクロール管理用変数 */ int g_iDy; /* ゲーム内時間カウンタ */ DWORD g_dwCount, g_dwTime; /* アプリケーション終了フラグ */ volatile BOOL g_bExit; DWORD WINAPI gameThread(LPVOID lpArg); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MSG msg; WNDCLASS wndclass; RECT recWnd = {0, 0, 479, 479}; g_hInstance = hInstance; /* ウインドウクラス設定 */ wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "THREADSC"; RegisterClass(&wndclass); /* ウインドウサイズ計算 */ AdjustWindowRect(&recWnd, WS_OVERLAPPEDWINDOW, FALSE); /* ウインドウ作成 */ g_hwMain = CreateWindow("THREADSC", "ゲームスレッドスクロール", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, recWnd.right - recWnd.left, recWnd.bottom - recWnd.top, NULL, NULL, hInstance, NULL); /* ウインドウを表示 */ ShowWindow(g_hwMain, iCmdShow); UpdateWindow(g_hwMain); /* 終了フラグリセット */ g_bExit = FALSE; /* メインループ */ do { /* メッセージ処理 */ if (GetMessage(&msg,NULL,0,0) == 0) { g_bExit = TRUE; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } while (!g_bExit); return (int)msg.wParam; } /* ウインドウプロシージャー */ LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; int i, j, r, g, b; switch (iMsg) { case WM_CREATE: hdc = GetDC(0); ZeroMemory(&g_biScroll, sizeof(g_biScroll)); /* スクロールビットマップ用BITMAPINFO設定 */ g_biScroll.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); g_biScroll.bmiHeader.biWidth = 480; g_biScroll.bmiHeader.biHeight = -512; g_biScroll.bmiHeader.biPlanes = 1; g_biScroll.bmiHeader.biBitCount = 32; g_biScroll.bmiHeader.biCompression = BI_RGB; /* スクロールビットマップ用DIBSection作成 */ g_hbmpScroll = CreateDIBSection(hdc, &g_biScroll, DIB_RGB_COLORS, (LPVOID *)(&g_lppxScroll), NULL, 0); /* スクロールビットマップ用メモリDC作成 */ g_hdcScroll = CreateCompatibleDC(hdc); g_hbmpScrollOld = (HBITMAP)SelectObject(g_hdcScroll, g_hbmpScroll); ZeroMemory(&g_biDisp, sizeof(g_biDisp)); /* 表示ビットマップ用BITMAPINFO設定 */ g_biDisp.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); g_biDisp.bmiHeader.biWidth = 480; g_biDisp.bmiHeader.biHeight = -480; g_biDisp.bmiHeader.biPlanes = 1; g_biDisp.bmiHeader.biBitCount = 32; g_biDisp.bmiHeader.biCompression = BI_RGB; /* 表示ビットマップ用DIBSection作成 */ g_hbmpDisp = CreateDIBSection(hdc, &g_biDisp, DIB_RGB_COLORS, (LPVOID *)(&g_lppxDisp), NULL, 0); /* 表示ビットマップ用メモリDC作成 */ g_hdcDisp = CreateCompatibleDC(hdc); g_hbmpDispOld = (HBITMAP)SelectObject(g_hdcDisp, g_hbmpDisp); ZeroMemory(&g_biMapTips, sizeof(g_biMapTips)); /* マップチップ用BITMAPINFO設定 */ g_biMapTips.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); g_biMapTips.bmiHeader.biWidth = 32; g_biMapTips.bmiHeader.biHeight = -32; g_biMapTips.bmiHeader.biPlanes = 1; g_biMapTips.bmiHeader.biBitCount = 32; g_biMapTips.bmiHeader.biCompression = BI_RGB; /* マップチップ用バッファ確保 */ g_lppxMapTips = (LPDWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 32 * 32 * 16); /* マップチップ用バッファをマップチップ用ポインタに分配 */ for (i = 0;i < 4;i++) { g_alppxMapTip[i] = g_lppxMapTips + i * 32 * 32; } /* 4種類のマップチップ作成 */ for (i = 0;i < 32;i++) { for (j = 0;j < 32;j++) { r = 128 + rand() % 128; g = 128 + rand() % 128; b = 128 + rand() % 128; g_alppxMapTip[0][j + i * 32] = r << 16; g_alppxMapTip[1][j + i * 32] = g << 8; g_alppxMapTip[2][j + i * 32] = b; g_alppxMapTip[3][j + i * 32] = (r << 16) + (g << 8) + b; } } /* 最初のスクロールビットマップ作成 */ for (i = 0;i < 16;i++) { for (j = 0;j < 15;j++) { StretchDIBits(g_hdcScroll, j * 32, i * 32, 32, 32, 0, 0, 32, 32, g_alppxMapTip[rand() % 4], &g_biMapTips, DIB_RGB_COLORS, SRCCOPY); } } /* スクロール一初期化 */ g_iDy = 32; /* ゲームスレッド起動 */ g_hGameThread = (HANDLE)_beginthreadex(NULL, 0, gameThread, NULL, 0, &g_dwGameThreadID); break; case WM_PAINT: /* 描画処理 */ hdc = BeginPaint(hwnd, &ps); /* 表示ビットマップを描画 */ BitBlt(hdc, 0, 0, 480, 480, g_hdcDisp, 0, 0, SRCCOPY); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: /* 終了処理 */ /* 終了フラグをセットしてゲームスレッドに終了を指示 */ g_bExit = TRUE; /* ゲームスレッド終了待機 */ if (WaitForSingleObject(g_hGameThread, 2000) != WAIT_OBJECT_0) { TerminateThread(g_hGameThread, 0); } /* ゲームスレッドのハンドルを閉じる */ CloseHandle(g_hGameThread); /* GDIオブジェクト削除 */ SelectObject(g_hdcScroll, g_hbmpScrollOld); SelectObject(g_hdcDisp, g_hbmpDispOld); DeleteObject(g_hbmpScroll); DeleteObject(g_hdcScroll); DeleteObject(g_hbmpDisp); DeleteObject(g_hdcDisp); /* マップチップ用バッファ解放 */ HeapFree(GetProcessHeap(), 0, g_lppxMapTips); PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; } /* ゲームスレッド関数 */ DWORD WINAPI gameThread(LPVOID lpArg) { int i; timeBeginPeriod(1); g_dwTime = timeGetTime(); do { if (timeGetTime() - g_dwTime > 16) { /* 今回の処理時間を記録 */ g_dwTime = timeGetTime(); if (g_iDy <= 0) { /* スクロール終了 */ /* スクロールビットマップを1チップ分下にずらして描画 */ BitBlt(g_hdcScroll, 0, 32, 480, 480, g_hdcScroll, 0, 0, SRCCOPY); /* スクロールビットマップの最上段にマップチップ描画 */ for (i = 0;i < 15;i++) { StretchDIBits(g_hdcScroll, i * 32, 0, 32, 32, 0, 0, 32, 32, g_alppxMapTip[rand() % 4], &g_biMapTips, DIB_RGB_COLORS, SRCCOPY); } /* スクロール位置初期化 */ g_iDy = 32; } else { /* スクロール中 */ /* スクロールビットマップをずらしながら表示ビットマップに描画 */ BitBlt(g_hdcDisp, 0, 0, 480, 480, g_hdcScroll, 0, g_iDy, SRCCOPY); /* スクロール位置更新 */ g_iDy += g_iDdy; /* ウインドウ再描画 */ InvalidateRect(g_hwMain, NULL, FALSE); } } Sleep(1); } while (!g_bExit); timeEndPeriod(1); return 0; }