マップチップの配置と描画の方法

概要

最終更新日:2020/02/19

マップチップの配置と描画についての説明を書いた記事です。
この記事は以下の内容を知りたい方に向けて書いています。
  • マップチップとは何か知りたい
  • 配置の基本の方法を知りたい
  • 描画の方法を知りたい

サンプル

サンプルはここからダウンロードでき、環境については以下の内容となっています。

開発環境
VSのバージョン DirectXのバージョン
VisualStudio 2019 DirectX9

マップチップとは

マップチップとは同じサイズの画像を複数用意してタイル上に並べて表示する手法です。
2Dゲームのステージを作成する時などに使用されます。
チップの配置方法は単純なため、CSVなどを使ってプランナーさんなどが
ステージを構築することができます。

2d_game_0018

上の画像の赤線が引かれているブロックがマップチップです。

マップチップ画像

マップチップの画像は上で書いている通り、同じサイズの画像を複数用意します。

2d_game_0020

上の画像は統合画像になっており、「1~15」までの画像を
マップチップとして使えます。
今回のマップチップ一つのサイズは「64×64」で統一しています。
左上が空白になっていますが、この理由は次の項目で説明します。

配置方法

マップチップの配置は配列を使用して行います。
まず、配列は「2次元配列」で用意をします。
これは、縦と横でタイル状に並べていくことを分かりやすくするためです。
この時の配列のサイズを割り出す計算は以下の式を使用します。
  • 配列[ステージの縦幅 / チップの縦幅][ステージの横幅 / チップの横幅]
上の式の通り、ステージのサイズをチップサイズで割るので、
ステージのサイズはチップのサイズで割り切れるサイズにします。
また、チップのサイズからステージのサイズを割り出す考え方もあります。
    チップのサイズ => 64 × 64
    配列のサイズ(単位はチップの数) => [20][15]
    ステージのサイズ => 横幅:64 * 15 縦幅:64 * 20
サンプルではステージサイズをチップサイズで割る式を使用して
配列のサイズを割り出しています。

#define STAGE_WIDTH (640)					// ステージの横幅
#define STAGE_HEIGHT (320)					// ステージの縦幅
#define MAPCHIP_WIDTH (64)					// マップチップの横幅
#define MAPCHIP_HEIGHT (64)					// マップチップの縦幅
#define MAP_SIZE_WIDTH (STAGE_WIDTH / MAPCHIP_WIDTH)		// MAPの横幅(値はチップ数)
#define MAP_SIZE_HEIGHT (STAGE_HEIGHT / MAPCHIP_HEIGHT)		// MAPの縦幅(値はチップ数)

// マップチップ配列
int g_MapChipList[MAP_SIZE_HEIGHT][MAP_SIZE_WIDTH]
{
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
	{ 1, 0, 0, 0, 0, 3, 3, 0, 0, 1},
	{ 1, 0, 2, 2, 0, 0, 0, 0, 0, 1},
	{ 1, 0, 0, 0, 0, 0, 4, 4, 0, 1},
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};

配列の要素にはマップチップの番号を設定します。
番号は統合画像ならば左上の画像を0とするの基本です。
アクションゲームなどで、チップを配置しない場所が存在することがあります。
そのような時に何も配置しない数字として「0」を使うことが多いので、
チップ番号の0に当たる位置には画像を配置しないようにしています。

また、サンプルでは分かりやすいように配列に対して要素を直接設定していますが、
本来はCSVファイルやテキストファイルなどの外部ファイルで
マップチップの番号を設定しておきます。
そして、そのファイルをゲーム中に読み込んで配列を完成させます。

描画方法

マップチップの描画は、マップチップを一括で全て描画するのではなく、
一枚一枚に描画処理を実行して描画します。
描画の流れとして、まずは統合画像の縦と横のチップ数を調べます。

// テクスチャのサイズとマップチップのサイズから横と縦のチップ数を割り出す
int width_chip_num = (int)texture_data->Width / MAPCHIP_WIDTH;
int height_chip_num = (int)texture_data->Height / MAPCHIP_HEIGHT;

次に、配列の全ての要素にアクセスできる繰り返し処理を書きます。


for (int i = 0; i < MAP_SIZE_HEIGHT; i++)
{
	for (int j = 0; j < MAP_SIZE_WIDTH; j++)
	{
		
	}
}

繰り返しの中では要素を取り出しますが、この要素が無効の値の時はcontinueをして、
その要素の処理を中止します。
// マップチップ番号取得
int chip_id = g_MapChipList[i][j];

// 無効な値かをチェック
if (chip_id == 0)
{
	continue;
}

番号が有効の場合は、マップチップの番号からテクスチャ座標を割り出します。
算出の式は以下の通りです。
  • X座標 = (マップチップ番号 % テクスチャのX軸のチップ数) * マップチップの横幅
  • Y座標 = (マップチップ番号 / テクスチャのY軸のチップ数) * マップチップの縦幅
// chip_idからチップのテクスチャ座標を割り出す
float chip_pos_x = (float)(chip_id % width_chip_num) * MAPCHIP_WIDTH;
float chip_pos_y = (float)(chip_id / height_chip_num) * MAPCHIP_HEIGHT;

あとは描画座標を割り出します。
描画座標は配列[0][0]を原点として考えるので、式は以下の通りです。
  • X座標 = マップチップの横幅 * X軸の配列番号
  • Y座標 = マップチップの縦幅 * Y軸の配列番号
// 描画座標を割り出す
float position_x = MAPCHIP_WIDTH * x;
float position_y = MAPCHIP_HEIGHT * y;

これで描画のための情報はほぼそろったので描画を行います。

2d_game_0019