スクロール表示の原理

ゲームでよく使われる横スクロール表示の実験です。ビットマップ作成に一定間隔の処理、マップチップの描画とゲームプログラミングの演習にも適していますね。

Startボタンを押すと右にスクロールしていきます(ゲームプログラミング開発メモに4方向マップスクロールもあり)。

スクロールさせるマップとパーツ

 スクロールさせるには、スクロール表示する「世界」を表したマップと海や山、草原などのドット絵パーツを用意します。マップは、海を0草原を1などという数値で表現して、表示する時にその数値を見て海(0)や草原(1)のパーツを表示して行くわけです。マップの座標は左上を(0、0)とします。
 今回は実験なのでマップデータは乱数で作って、パーツも簡単な図形を描くだけにしておきましょう。パーツの大きさは16*16ピクセルとし、1画面に表示するパーツの数は横16*縦16パーツとしました。スクロールする方向は右方向だけ、マップでいうとを増やす方向という事になります。マップの方は横128*縦16もあれば良いですね。パーツは、イメージの配列parts[]に入っていて、0番のイメージはparts[0]、 1番のイメージはparts[1]となっていますから、このマップを表示する時は、

  for (i=0;i<16;i++) /*最初の画面を作成*/
      for (j=0;<16;j++)
          g_screen.drawImage(parts[map[j][i]],j*16,i*16,this);

 という感じになります。map[x][y]を見れば(x,y) にある地形が読め、今回はその地形番号がそのまま表示すべきイメージの番号になっているわけです(実際のゲームではマップに地形だけでなくイベントなどの情報も入るので、地形を読み出す時にはもう少し処理が必要になります)。

 次に、イメージを2枚用意します。一枚は実際に画面に表示する表示用のイメージで、もう1枚はスクロールするマップを描くためのバッファです。大きさは表示用イメージの方が256*256 ピクセル(マップパーツ16*16個分)でスクロール用が272*256 ピクセル(マップパーツ17*16個分)。スクロール表示させる時には、いったんバッファの方にパーツを描いて、そのバッファイメージを「ずらしながら」表示用イメージに転送します。

スクロール表示の方法

 今回は、右スクロールだけなので横方向のみを考えましょう。まず、現在のから右方向に横17個分のパターンを、スクロール用の作業用バッファイメージに描き出します。こうするとスクロール用イメージには、現在表示されている16*16個のパターンの他に右端に1列その右側のパターンが描かれている事になりますね。この部分がスクロール表示の本質ともいうべき部分です。
 次にこのバッファのイメージを、バッファの左端を表示用イメージの表示領域の左端にあわせて表示します。こうするとバッファの画面にはバッファの左上端から16*16パーツが表示され、右端の1パーツ16ピクセル分は表示用イメージからあふれて表示されません。この状態で、バッファの表示位置を1ピクセル左にづらして見ましょう。すると、見えなかった16ピクセルのうち1ピクセルだけは、表示領域に入るので見えるようになりますね。表示用イメージの左端の方は、 座標がマイナスになるので、クリッピングされ表示されません。
 後は、これと同じ事を16回繰り返せば(表示開始のx 座標を表示用イメージの0から-15に順次ずらしていけば)見えなかった右端16ピクセル分のイメージが、少しづつ表示される事になります。そう、つまり「スクロール」表示されるわけです。

スクロール処理部分のリスト

  public void run() {

      int i,j,x;

      x=0; // 現在位置をマップの左端に設定

      while(running && x<110) { // 右端に来るまで右方向スクロール

          for (i=0;i<16;i++) // バッファにスクロールさせるイメージを描く
              for (j=0;j<17;j++)
                  g_scrol.drawImage(parts[map[j+x][i]],j*16,i*16,this);

          for (i=0;i<16;i++) { // バッファを左にずらしながら表示

              g_screen.drawImage(scrol,-i,0,this);

              // 表示用イメージをアプレットに描画
              Graphics g=getGraphics();
              paint(g);
              g.dispose();

              try { Thread.sleep(10); } // ウエイト
              catch (InterruptedException e) {}


          }

          x++; // マップ上の位置を1つ右にずらす

      }

  }

 今回のプログラムはJavaで書いてありますが、他の処理系でも原理は同じです。ただし、DelphiVC++ などでWindowsアプリケーションにする時には、スレッドを作るまでもないでしょう。ループさせながら、適当に再描画をかけてやれば十分です。

プログラムソース表示

ゲーム制作研究室へ戻る