ゲームプログラミング練習帳
ビットマップの作成からスクロール、イベント処理までの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をリンクしてからビルドしてください。