ゲームプログラミング練習帳
ビットマップの作成からスクロール、イベント処理までのRPG制作

RPG製作−1.画面構成と描画

 これまで、スクロールやマップ情報などゲームプログラミングに関するいろいろな「実験」をして来ました。ただ、今まで作ってきたのはいわば「部品」とも言うべき断片です。そろそろこの「部品」をまとめて、実際に「ゲーム」を創ってみましょう。創るのは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をリンクしてからビルドしてください。

プログラムソース表示

戻る