ゲームプログラミング練習帳
ビットマップの作成からスクロール、イベント処理までのRPG制作
これまで、スクロールやマップ情報などゲームプログラミングに関するいろいろな「実験」をして来ました。ただ、今まで作ってきたのはいわば「部品」とも言うべき断片です。そろそろこの「部品」をまとめて、実際に「ゲーム」を創ってみましょう。創るのはDirectDrawベースのRPG。やっぱり私が一番創りたいのはRPG(というより「仮想世界」)で、技術的にもアクション性の弱いRPGは比較的作りやすいですからね。
さらに、今回の製作を通してDirectDrawの実践的な使い方やグラフィックの扱いなどに慣れて行く、という目的もあります。ゲーム製作は、プログラミングやシナリオ・グラフィックなどを始めとする「創造力」の「総合演習」であり集大成なのですから。
画面構成は、全体を800×600ピクセルの全画面DirectDrawサーフェス、マップを1パーツ32×32ピクセル、15×15パーツの480×480ピクセルとします。マップは、左寄せで描いて右側の余った場所に主人公のステータスを表示しましょう。メッセージに関しては、下の方に独立したウインドウを作る事も検討したのですが、上下方向の余裕が600−480=120ピクセルしかないのでちょっと無理ですね。通常の全画面RPGのように、必要に応じてマップ画面の中にウインドウを出す事にしましょう。
今回は、DirectDrawで複数のサーフェスを扱いながらサーフェスを透過処理する実験として画面全体の背景とマップ画面、それにマップ画面の「枠」を描くプログラムを作ってみました。まず、背景のサーフェスとマップのサーフェス、それにマップチップ・主人公キャラで合計5枚のサーフェスを作成し、描画の時には順次それらのサーフェスをバックバッファにBltFast、それをフリップし表示しています。
| 背景 | lpDDSScreen |
|---|---|
| マップ | lpDDSMap |
| マップチップ | lpDDSParts[2] |
| 主人公 | lpDDSChr |
マップの大きさは64×64パーツ。マップのパーツ(今回は水と平野の2種類のみ)配置をBYTE map[64][64]に、通過の可否やイベントなどのマップの属性をWORD mInfo[64][64]に格納しています。マップ属性は、最上位を通過フラグとしてここがセットされていれば通行可能、としました。今回は、通過フラグしか使いませんので、通過フラグがセットされていない(属性値が0)なら通過不可、セットされている(属性値が32768)なら通過可能を意味します。
マップのスクロールは以前とまったく同じで、マップ画面より一回り大きなサーフェス(17×17パーツ)にマップチップを描いておき、そのサーフェスの一部をずらしながら15×15パーツ分ずつ表示して行きます。
// マップサーフェスに画面より一回り大きな範囲でマップ描画
for (i=0;i<17;i++)
for (j=0;j<17;j++)
lpDDSMap->BltFast(j*32,i*32,lpDDSParts[map[j+x-8][i+y-8]],
&recChr,DDBLTFAST_NOCOLORKEY|DDBLTFAST_WAIT);
後はメインループでカーソルキー入力をチェックし、スクロール方向を決定。スクロールフラグfScをセットして次の周期からスクロールを開始しましょう。
・メインループの処理
if (fSc) { // スクロール中の処理
// バックバッファに背景を描画
lpDDSBack->BltFast(0,0,lpDDSScreen,&recScreen,DDBLTFAST_NOCOLORKEY|DDBLTFAST_WAIT);
iDx+=iDdx;
iDy+=iDdy;
rec.left=iDx;
rec.top=iDy;
rec.right=iDx+480;
rec.bottom=iDy+480;
// スクロール終了時の処理
if (iDx==iScd||iDx==64-iScd||iDy==iScd||iDy==64-iScd) {
makeBG(iX,iY); // スクロール後のマップ画面を描画
iDx=0;
iDy=0;
iDdx=0;
iDdy=0;
fSc=FALSE; // スクロールフラグリセット
return;
}
// バックバッファにマップを描画
lpDDSBack->BltFast(32,88,lpDDSMap,&rec,DDBLTFAST_NOCOLORKEY|DDBLTFAST_WAIT);
// バックバッファに主人公を描画(透過処理)
lpDDSBack->BltFast(224+32,224+88,lpDDSChr,&recChr,DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT);
// バックバッファをフリップ
lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);
} else { // スクロール時以外
iDx=32;
iDy=32;
iDdy=0;
iDdy=0;
// カーソルキーで移動
if (GetAsyncKeyState(VK_UP)<0 && mInfo[iX][iY-1]>32767) {
iY--; // 主人公の位置更新
iDdx=0; // スクロール方向設定
iDdy=-iScd;
fSc=TRUE; // スクロールフラグセット
} else if (GetAsyncKeyState(VK_RIGHT)<0 && mInfo[iX+1][iY]>32767) {
iX++;
iDdx=iScd;
iDdy=0;
fSc=TRUE;
} else if (GetAsyncKeyState(VK_DOWN)<0 && mInfo[iX][iY+1]>32767) {
iY++;
iDdx=0;
iDdy=iScd;
fSc=TRUE;
} else if (GetAsyncKeyState(VK_LEFT)<0 && mInfo[iX-1][iY]>32767) {
iX--;
iDdx=-iScd;
iDdy=0;
fSc=TRUE;
}
}
カーソルキーで上下左右に移動できます。終了する時にはエスケープキーを押してください。
プログラムをコンパイルする時には、DirectX5以上のSDKをインストールする必要があります。ソースをダウンロードしたら、拡張子をcppにしてプロジェクトの設定でddraw.libをリンクしてからビルドしてください。