Skip to content
第08回 画像リソースの管理

1 / 4 画像の識別と対応表の設計 ​

このステップの目的

画像IDとファイルパスを対応表で結び、ゲーム側の処理とファイル名を分けて管理する設計を理解します。

画像ID(enum class Id)による抽象化 ​

プレイヤーや敵のクラスでは、Assets/Images/Player.pngのようなファイルパスを直接扱いません。
代わりに、ImageManager::Idという列挙型のシンボルを指定して描画を依頼します。

ImageManager.hcpp
class ImageManager
{
public:
    // ゲーム内で使用する画像リソースの識別子
    enum class Id
    {
        Player,
        PlayerShot,
        Enemy,
        EnemyShot,
        Background,
        Count       // 画像の総数を表す特殊な列挙子
    };
};

ファイル名を直接指定せず、IDで画像を扱うと、次の利点があります。

画像名やフォルダ構成が変わっても、Player.cppやEnemy.cppなどのゲーム処理を修正する必要はありません。
存在しない画像IDを指定すると、コンパイルエラーになります。文字列でパスを指定する場合と違い、入力ミスをその場で検出できます。

対応表(ImageTable)による一括管理 ​

画像IDとファイルパスの対応は、ImageManager.cppの無名名前空間にあるImageTableでまとめて管理します。

ImageManager.cppcpp
using ImageId = ImageManager::Id;

struct ImageEntry
{
    ImageId id;
    const wchar_t* path;
};

constexpr std::array<ImageEntry, static_cast<std::size_t>(ImageId::Count)> ImageTable =
{
    ImageEntry { ImageId::Player,     L"Assets/Images/Player.png" },
    ImageEntry { ImageId::PlayerShot, L"Assets/Images/Bullet.png" },
    ImageEntry { ImageId::Enemy,      L"Assets/Images/Enemy.png" },
    ImageEntry { ImageId::EnemyShot,  L"Assets/Images/EnemyShot.png" },
    ImageEntry { ImageId::Background, L"Assets/Images/Background.png" }
};

ImageId::Countで配列の容量を決めます。ただし、初期化する行が少なくても残りの要素が初期化されるため、登録行数の不足はこれだけでは検出できません。各IDを一度ずつ登録したか、表と読み込み結果を確認します。

一括読み込みとエラーハンドリング ​

起動時のImageManager::LoadAll()では、対応表を先頭から順に調べます。DXライブラリのLoadGraph()で画像を読み込み、ハンドルを取得します。

ImageManager.cppcpp
ImageManager::LoadResult ImageManager::LoadAll()
{
    for (const ImageEntry& entry : ImageTable)
    {
        std::size_t index = ToIndex(entry.id);
        handles[index] = LoadGraph(entry.path);

        if (handles[index] == -1)
            return { false, entry.path };
    }

    return { true, {} };
}

一つでも画像の読み込みに失敗したら、そのパス(entry.path)を結果構造体へ記録し、直ちに処理を中断します。
これにより、呼び出し元であるGame::Run()は「画像ファイルが見つかりません: Assets/Images/Bullet.png」といった分かりやすいエラーメッセージを表示して安全に終了できます。

チェックリスト
  • キャラクターがファイルパスを直接持たず、ImageManager::Idを指定して描画を依頼している
  • 画像IDとファイルパスがImageTableで一元管理されている理由を説明できる
  • Id::Countで容量を決め、登録漏れと重複を別に確認している
  • 読み込み失敗時にエラーとなったファイルパスを特定できる仕組みを理解している