シューティングゲームのプログラミングにおける移動や被弾などの判定処理には、いろいろな方法があります。スクリーン上の座標を利用したり、DIBやDirectXを使っているのならピクセルの「色」を使う手もあるでしょう。ただ、動きがある程度「粗い」ものでも良ければ、もっと簡単な方法があります。 今回は、この方法で自機の移動や弾丸の発射処理を行うプログラムを開発してみましょう。 スクリーンのグリッドと自機・弾の移動今回は、ゲーム画面を512×512ピクセルにして画面を32×32のグリッドに分けます。つまり、グリッドの大きさは16×16ピクセルになるわけです。自機や弾の位置もこのグリッドであらわす事にして、自機の大きさは32×32ピクセルとしました(つまり、自機は2×2グリッドを占める)。 次に自機の弾丸ですが、こちらはグリッド一つ分16×16で十分でしょう。今回のプログラムでは、グリッドの右端に2ピクセル分の白い縦線を引いておきました。弾丸の移動は、グリッドの管理配列(BYTE map[32][33])を用意して処理します。この配列は、グリッドの情報を管理するものでmap[x][y]=2なら弾丸が(x, y)にある、という事にしました。発射時の処理は、弾丸が発射されたら自機のすぐ上の座標の管理配列に2を書きこんで、後はだんだんと上に移動します。後は、画面を描画する時に管理配列を見て弾丸がある場所に弾丸を表示すれば良いですね。 移動する時の移動量は、自機が一度に1グリッドで弾丸が2グリッドとしましょう。 画面表示とキー入力ゲームの画面はDIBSectionにします。512×512のビットマップを作成し、描画の時はまず背景用のバッファ(512×512バイト)を描いて、その後に透過処理によるソフトウエアスプライトでキャラクタのパターンを描画しましょう。 ・移動・描画処理関数 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; /* 今回の時間を記録 */ } こうしてDIBSectionのビットマップに作成した画面は、WM_PAINTメッセージ処理で描画します。 プログラムVC++などでプログラムをビルドし起動したら、カーソルキーで移動してスペースキーで弾丸を発射してみてください。フレームレートも表示していますから、メインループの周期を変えて反応やフレームレートがどうなるか試してみるのも良いでしょう。 今回のプログラムをスケルトンにして、簡単なゲームを制作してみてください。 |