一枚絵の背景ではなく、2DのRPGゲームの用に背景用の小さな画像をタイル上に並べて、一枚の背景画像にする方法を紹介する。
例えばこんな感じの背景を作成する。![]()
この背景は、32×32ピクセルで作成した背景用の画像(マップチップ)を横に20個、縦に15個並べ、640×480ピクセルの背景を作成している。
マップの元となる画像を作成する。今回は、フリーの素材を使用する。
![]()
32×32で作成した背景画像のパーツをタイル上に並べたものである。これらを好きなように並べ替え、背景として表示することを考える。
マップチップに番号を付けると、次のようになる。
![]()
そして、マップチップを好きなように並べ替え、例えば次のようにバック・バッファに貼り付けることを考える。
02 02 02 02 00 00 00 00 00 00 00 02 02 02 02 02 02 02 02 02 02 00 00 00 00 00 00 21 02 00 00 00 21 21 21 21 21 21 21 02 02 00 02 02 02 02 02 00 02 00 02 02 02 02 02 02 02 00 02 02 02 00 00 00 00 21 02 00 02 00 00 00 00 00 00 00 02 00 00 02 02 00 00 02 21 21 02 00 02 00 00 02 00 00 02 00 02 02 00 02 02 00 00 02 02 02 02 00 40 41 42 02 00 00 02 00 00 00 00 02 02 00 00 00 00 00 00 00 60 61 62 00 00 00 02 02 02 02 02 02 00 00 02 02 02 02 02 02 80 81 82 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 02 00 02 02 02 02 02 02 00 02 02 00 02 02 02 02 02 02 02 00 02 00 02 00 00 00 00 02 00 02 02 00 02 00 00 00 00 00 00 00 02 00 02 00 02 00 00 02 00 02 02 00 02 00 00 00 02 02 02 02 02 00 02 00 02 00 00 02 00 02 02 00 02 02 02 00 00 00 00 00 00 00 02 00 02 00 00 02 00 02 02 00 02 00 00 00 02 21 21 21 21 21 21 21 02 00 00 00 00 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 このとき、貼り付ける番号をデータとして持てば、そのデータを変更するだけで背景を自由に変えることができる。
マップデータを1次元配列で考えたプログラムを紹介する。ダウンロードし、DDraw15_1という名前でプロジェクトを作成し、ビルドして結果を確かめてみよう。
《解説1:グローバル変数の宣言》
static int MapData[MAP_HEIGHT * MAP_WIDTH] = { // マップデータ 02, 02, 02, 02, 00, 00, 00, 00, 00, 00, 00, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 00, 00, 00, 00, 00, 00, 21, 02, 00, 00, 02, 02, 02, 02, 02, 02, 02, 02, 02, ・ ・ ・ 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 00, 02, 02, 02, 02 }; static RECT rcMapChip[MAP_HEIGHT * MAP_WIDTH]; // 表示する矩形のセット
- MapData[MAP_HEIGHT * MAP_WIDTH]
- マップデータを格納する1次元配列。MAP_WIDTHとMAP_HEIGHTはcommon.hに宣言してある。
ファイルから読み込むようにすれば、プログラムを変更することなくマップデータを変更できる。- rcMapChip[MAP_HEIGHT * MAP_WIDTH]
- バック・バッファ上にどの矩形を転送するかをセットするための1次元配列。
転送時にマップデータの番号から、転送する矩形を計算してもいいが、ゲーム中には余計な計算をさせたくないので初期化処理でセットしておく。《解説2:初期化処理》
//------------------------------------------------------- 各変数の初期化 /* マップデータを元に、表示する矩形をセットする */ for (i=0 ; i<MAP_HEIGHT * MAP_WIDTH ; i++) { rcMapChip[i].left = (MapData[i] % MAP_WIDTH) * 32; rcMapChip[i].top = (MapData[i] / MAP_WIDTH) * 32; rcMapChip[i].right = rcMapChip[i].left + 32; rcMapChip[i].bottom = rcMapChip[i].top + 32; }MapData[i]の数値(マップデータの番号)から、そのマップのある矩形を計算して、転送用矩形配列に格納する。メモリは余分に消費するが、描画時に毎回計算する必要がなくなるため、ゲームループが早くなる。
《解説3:背景描画処理》
int i, x, y; /* 表示する矩形を順番に描画する */ for (i=0 ; i<MAP_HEIGHT * MAP_WIDTH ; i++) { x = (i % MAP_WIDTH) * 32; y = (i / MAP_WIDTH) * 32; hRet = g_pDDSBack->BltFast(x, y, g_pDDSGame, &rcMapChip[i], DDBLTFAST_NOCOLORKEY); if (hRet != DD_OK) return; }マップデータを元に、マップの矩形をバック・バッファに転送していく。転送先x、y座標は毎回計算しているが、この処理も初期化処理でやってもいいかもしれない。
マップチップの種類によって、通常の道なのか障害物なのかを使い分ける場合など、データを2次元で持ったほうがいい場合がある。そこで、データを2次元で持つようにプログラムを修正してみる。
《グローバル変数の宣言》
static int MapData[MAP_HEIGHT][MAP_WIDTH]= { // マップデータ 02, 02, 02, 02, 00, 00, 00, 00, 00, 00, 00, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 00, 00, 00, 00, 00, 00, 21, 02, 00, 00, 02, 02, 02, 02, 02, 02, 02, 02, 02, ・ ・ ・ 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 00, 02, 02, 02, 02 }; static RECT rcMapChip[MAP_HEIGHT][MAP_WIDTH]; // 表示する矩形のセット※2次元配列の1つ目をy軸、2つ目の引数をx軸として宣言する。
《初期化処理》
int x, y; //------------------------------------------------------- 各変数の初期化 /* マップデータを元に、表示する矩形をセットする */for (y=0 ; y<MAP_HEIGHT ; y++){for (x=0 ; x<MAP_WIDTH ; x++){ rcMapChip[y][x].left = (MapData[y][x]% MAP_WIDTH) * 32; rcMapChip[y][x].top = (MapData[y][x]/ MAP_WIDTH) * 32; rcMapChip[y][x].right = rcMapChip[y][x].left + 32; rcMapChip[y][x].bottom = rcMapChip[y][x].top + 32; } }《背景描画処理》
intmx, my, x, y; /* 表示する矩形を順番に描画する */for (my=0 ; my<MAP_HEIGHT ; my++){for (mx=0 ; mx<MAP_WIDTH ; mx++){ x =mx* 32; y =my* 32; hRet = g_pDDSBack->BltFast(x, y, g_pDDSGame, &rcMapChip[my][mx], DDBLTFAST_NOCOLORKEY); if (hRet != DD_OK) return; } }
2でダウンロードしたプログラムを、2次元でマップデータを管理するよう、修正しなさい。
作成したマップチップ画像から、マップ・データを作るのは非常に手間がかかる。そこで、
マップ・エディタと呼ばれるソフトを使い、マップ・データをビジュアル的に作成することができる。マップ・エディタにはフリーのものが多いので、いろいろ試してみて、自分が使い易いと思うものを利用しよう。