/* シューティングゲーム>自機の移動と弾丸発射 1999/ 1/22 宍戸 輝光 */ #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); void draw(void); LPBYTE lpBuf,lpScreen,lpBG,lpChr; LPBITMAPINFO lpDIB; LPRGBQUAD lpRGB; HDC hdcWin,hdcMem; HWND hwMain; HBITMAP hBMP; BYTE map[32][34]; DWORD dwTime,dwPreTime; int iX=16,iY=8; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ MSG msg; WNDCLASSEX wndclass ; int i,j; wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "CWindow"; wndclass.hIconSm = NULL; RegisterClassEx (&wndclass); hwMain=CreateWindow ("CWindow",NULL, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,600,560, NULL,NULL,hInstance,NULL); lpBuf=(LPBYTE)GlobalAlloc /* バッファ用メモリ確保 */ (GPTR,sizeof(BITMAPINFO)+255*sizeof(RGBQUAD)+512*512*2+32*32); lpDIB=(LPBITMAPINFO)lpBuf; /* バッファ用メモリを分配 */ lpRGB=(RGBQUAD*)(lpBuf+sizeof(BITMAPINFOHEADER)); lpScreen=lpBuf+sizeof(BITMAPINFO)+255*sizeof(RGBQUAD); lpBG=lpScreen+512*512; lpChr=lpBG+512*512; lpDIB->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); /* BITMAPINFO構造体 */ lpDIB->bmiHeader.biWidth=512; lpDIB->bmiHeader.biHeight=512; lpDIB->bmiHeader.biPlanes=1; lpDIB->bmiHeader.biBitCount=8; lpDIB->bmiHeader.biCompression=BI_RGB; lpDIB->bmiHeader.biSizeImage=0; lpDIB->bmiHeader.biXPelsPerMeter=0; lpDIB->bmiHeader.biYPelsPerMeter=0; lpDIB->bmiHeader.biClrUsed=0; lpDIB->bmiHeader.biClrImportant=0; lpDIB->bmiColors[0]=lpRGB[0]; /* カラーテーブルの先頭 */ for (i=1;i<254;i++) { // パレット作成 lpRGB[i].rgbRed=128+rand() % 96; lpRGB[i].rgbGreen=128+rand() % 96; lpRGB[i].rgbBlue=128+rand() % 128; } lpRGB[253].rgbRed=0; lpRGB[253].rgbGreen=224; lpRGB[253].rgbBlue=192; lpRGB[254].rgbRed=200; lpRGB[254].rgbGreen=192; lpRGB[254].rgbBlue=224; lpRGB[255].rgbRed=255; lpRGB[255].rgbGreen=255; lpRGB[255].rgbBlue=255; for (i=0;i<16;i++) /* 自機のパターン作成 */ FillMemory(lpChr+(i+1)*32+(i/2),32-i,254); for (i=4;i<28;i++) FillMemory(lpChr+i*32+8,16,253); for (i=0;i<4;i++) FillMemory(lpChr+(i+28)*32+8+i*2,16-i*4,253); for (i=0;i<512*512;i++) if (rand() % 300==0) lpBG[i]=1+rand() % 253; /* DIB とウインドウのDC からDIBSection を作成 */ hBMP=CreateDIBSection (GetDC(hwMain),lpDIB,DIB_RGB_COLORS,(void **)&lpScreen,NULL,0); hdcMem=CreateCompatibleDC(GetDC(hwMain)); /* メモリDC を作成 */ SelectObject(hdcMem,hBMP); /* メモリDC にビットマップを選択 */ ShowWindow (hwMain,iCmdShow); // ウインドウを表示 UpdateWindow (hwMain); for (i=0;i<32;i++) for (j=0;j<32;j++) map[j][i]=0; dwTime=GetTickCount(); while (1) { /* メインループ */ if (PeekMessage (&msg,NULL,0,0,PM_NOREMOVE)) { if (!GetMessage (&msg,NULL,0,0)) // メッセージ処理 return msg.wParam ; TranslateMessage(&msg); DispatchMessage(&msg); } else draw(); // 描画処理 } } void draw(void) { int i,j,dwCount; char lpszStr[64]; RECT rec; if (GetTickCount()>dwTime+20) dwTime=GetTickCount(); else /* 前回の処理から20ms 以上経ってなければ戻る */ return; dwCount=dwTime-dwPreTime; /* 前回からの経過時間を計算 */ CopyMemory(lpScreen,lpBG,512*512); /* 背景描画 */ for (i=0;i<32;i++) /* 自機描画 */ for (j=0;j<32;j++) if (lpChr[j+i*32]!=0) lpScreen[iX*16+j+(iY*16+i)*512]=lpChr[j+i*32]; for (i=0;i<31;i++) /* 弾丸描画 */ for (j=0;j<32;j++) if (map[j][i]==2) { lpScreen[j*16+15+(i*16+7)*512]=255; lpScreen[j*16+15+(i*16+8)*512]=255; } /* キー入力取得 */ if (GetAsyncKeyState(VK_UP)<0 && iY<30) /* 上キー */ iY++; /* 自機の位置を更新 */ if (GetAsyncKeyState(VK_RIGHT)<0 && iX<30) iX++; if (GetAsyncKeyState(VK_DOWN)<0 && iY>0) iY--; if (GetAsyncKeyState(VK_LEFT)<0 && iX>0) iX--; if (GetAsyncKeyState(VK_SPACE)<0) /* 弾丸発射 */ map[iX][iY]=2; /* 管理配列に弾丸を書きこむ */ for (i=31;i>=0;i--) /* 弾丸を2グリッド上に移動 */ for (j=0;j<32;j++) if (map[j][i]==2) { map[j][i+2]=2; map[j][i]=0; } if (dwCount!=0) { /* フレームレートを表示 */ wsprintf(lpszStr,"FrameRate=%3d",(DWORD)(1000/dwCount)); SetTextColor(hdcMem,RGB(255,255,255)); SetBkMode(hdcMem,TRANSPARENT); rec.top=224; rec.left=0; rec.bottom=288; rec.right=511; DrawText(hdcMem,lpszStr,lstrlen(lpszStr),&rec, DT_CENTER|DT_SINGLELINE|DT_VCENTER); } InvalidateRect(hwMain,NULL,FALSE); UpdateWindow (hwMain); // 再描画 dwPreTime=dwTime; /* 今回の時間を記録 */ } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (iMsg) { case WM_PAINT: hdc=BeginPaint(hwnd,&ps); /* ゲーム画面を描画 */ BitBlt(hdc,8,8,512,512,hdcMem,0,0,SRCCOPY); EndPaint(hwnd,&ps); break; case WM_DESTROY : // 終了処理 GlobalFree(lpBuf); DeleteDC(hdcMem); /* デバイスコンテキスト開放 */ DeleteObject(hBMP); /* ビットマップ開放 */ PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }