Appearance
第15回 CSVから作るステージ
3 / 4 セルの役割を描画と配置へ分ける
このステップの目的
プレイヤー開始位置やゴールなどの「配置用目印」を地形データから分離し、定義表(TileDefinition)を用いて描画する仕組みを実装します。
配置用セルと地形セルの役割分離
CSV内には、レンガや苔石のような「地形ブロック」だけでなく、プレイヤーの初期位置(PlayerSpawn)やゴール地点(Goal)といった「目印」も配置されています。
これらをそのまま地形配列の中に残すと、後の衝突判定において「プレイヤーが開始地点のブロックに挟まる」「ゴール地点が硬い壁になって侵入できない」といった不具合が発生します。
そのため、読み込み時に配置用のセルを検出したら、その座標を中心点のワールド座標として専用のメンバ変数へ記録し、地形配列自体には「空間(Empty)」を代入します。
Stage.cpp(配置セルの分離)cpp
// タイルの中心座標を算出
const Vector2 tileCenter = {
x * static_cast<float>(tuning::stage::TileSize) + tuning::stage::TileSize * 0.5f,
y * static_cast<float>(tuning::stage::TileSize) + tuning::stage::TileSize * 0.5f
};
if (cell == StageCell::PlayerSpawn)
{
playerSpawnPosition_ = tileCenter;
cell = StageCell::Empty; // 地形としては空白にする
}
else if (cell == StageCell::Goal)
{
goalPosition_ = tileCenter;
cell = StageCell::Empty; // ゴールも地形判定上は空白にし、専用判定で扱う
cell = StageCell::Empty; // ゴールも地形としては空白にし、専用の判定で扱う
}この分離によって、地形ブロックとしての役割と、オブジェクトの出現場所としての役割が明確に分かれます。
定義表(TileDefinition)による条件分岐の排除
地形ブロックを描画する際、if (cell == Brick) や else if (cell == Moss) といった条件分岐を Draw() 内に並べると、タイルの種類が増えるたびに分岐処理が肥大化します。
そこで、ブロックの種類(StageCell)、描画する画像(ImageId)、および衝突判定の有無(isSolid)をまとめた定義表 TileDefinitions を用意します。
Stage.cppcpp
struct TileDefinition
{
StageCell cell;
ImageId imageId;
bool isSolid; // 通過できない固いブロックか
};
constexpr TileDefinition TileDefinitions[] =
{
{ StageCell::Brick, ImageId::Tile, true },
{ StageCell::Moss, ImageId::TileMoss, true }
};描画関数 Stage::Draw() では、各マスについて定義表を検索し、一致する画像を描画します。
Stage.cppcpp
void Stage::Draw(const ImageManager& images) const
{
for (int y = 0; y < mapHeight_; y++)
{
for (int x = 0; x < mapWidth_; x++)
{
const StageCell cell = cells_[y][x];
if (cell == StageCell::Empty)
continue;
DrawTile(x * TileSize, y * TileSize, cell, images);
}
}
const dxgame::Rect goalDrawRect = GetGoalDrawRect();
images.Draw(ImageId::Goal, goalDrawRect);
}この定義表を用いる構造により、新しいブロックを追加する際も定義表に1行追加するだけで描画と判定に対応できます。
チェックリスト
-
PlayerSpawnやGoalが地形配列から分離され、開始地点やゴールが壁にならないようになっている - 定義表(
TileDefinitions)により、条件分岐を乱立させずに地形を描き分けられる - タイルの元画像サイズにかかわらず、
TileSize(32ピクセル)四方で規則正しく描画されている