Appearance
第08回 画像とリソース管理
前回: 第07回 クラス分割入門 / 次回: 第09回 ゲーム状態
今回の授業内容
- DXライブラリで画像を読み込む
- 画像ハンドルを
ImageManagerで管理する - プレイヤー、弾、敵の描画を画像へ置き換える
- 画像がない場合は図形描画へ戻す
Assets/Imagesの配置ルールを確認する
今回の開始状態
第07回終了時点では、プレイヤー、弾、敵がクラスに分かれています。
描画はまだ図形だけです。
今回の終了時点では、画像がある場合は画像で描画し、画像がない場合は今までの図形で動くようにします。
変更するファイル
| ファイル | 変更内容 |
|---|---|
ImageManager.h / ImageManager.cpp | 画像の読み込み、取得、解放を追加する |
Game.h / Game.cpp | ImageManagerを所有し、初期化と終了処理で呼ぶ |
Player.cpp / Bullet.cpp / Enemy.cpp | 描画時に画像管理を参照する |
Assets/Images | 任意で画像素材を配置する |
ImageManagerを追加する
画像の種類は列挙型で表します。
cpp
enum class ImageId
{
Player,
Enemy,
Bullet,
Background,
Count
};ImageManagerは、画像ハンドルを配列で持ちます。
読み込みに失敗した画像は-1のまま扱います。
cpp
class ImageManager
{
public:
bool Initialize();
void Finalize();
int Get(ImageId id) const;
bool Has(ImageId id) const;
private:
int handles[static_cast<int>(ImageId::Count)] = {};
};Initialize()では、ファイルパスを1か所に集めます。
cpp
handles[ToIndex(ImageId::Player)] = LoadGraph(L"Assets/Images/Player.png");
handles[ToIndex(ImageId::Enemy)] = LoadGraph(L"Assets/Images/Enemy.png");
handles[ToIndex(ImageId::Bullet)] = LoadGraph(L"Assets/Images/Bullet.png");
handles[ToIndex(ImageId::Background)] = LoadGraph(L"Assets/Images/Background.png");描画側を差し替える
各クラスのDraw()は、ImageManagerを参照で受け取る形へ変更します。
cpp
void Player::Draw(const ImageManager& images) const
{
if (images.Has(ImageId::Player))
{
DrawGraph(
static_cast<int>(position.x - 16),
static_cast<int>(position.y - 16),
images.Get(ImageId::Player),
TRUE
);
return;
}
DrawTriangle(
static_cast<int>(position.x),
static_cast<int>(position.y - 18),
static_cast<int>(position.x - 16),
static_cast<int>(position.y + 14),
static_cast<int>(position.x + 16),
static_cast<int>(position.y + 14),
cyan,
TRUE
);
}画像がある場合は画像を描き、ない場合はこれまでの図形描画へ戻します。
この分岐により、素材がそろっていない状態でもゲームロジックの確認を続けられます。
Gameから画像管理を渡す
GameがImageManagerを所有し、描画時に各クラスへ渡します。
cpp
bool Game::Initialize()
{
images.Initialize();
player.Reset();
return true;
}
void Game::Finalize()
{
images.Finalize();
}cpp
player.Draw(images);
for (const Bullet& bullet : bullets)
bullet.Draw(images);動作確認
- 画像なしで実行し、図形描画のまま動くことを確認する
Assets/Images/Player.pngを追加し、プレイヤーだけ画像になることを確認する- ファイル名を一時的に変えて、図形描画へ戻ることを確認する
ImageManager::Finalize()で読み込んだ画像を解放していることを確認する
よくある問題
- 画像が表示されない場合は、実行時の作業ディレクトリから
Assets/Imagesが見えるか確認する - パスの大文字小文字が、ファイル名と一致しているか確認する
Draw()の引数を変えたら、呼び出し側もすべて修正する
今回の完成条件
ImageManagerで画像をまとめて管理できる- 画像がある場合だけ画像描画へ切り替えられる
- 画像がない場合でもゲームを実行できる
Assets/Imagesの配置ルールを説明できる
まとめ
今回は、画像素材を任意で使える構成にしました。
次回は、タイトル、プレイ中、結果画面をゲーム状態として整理します。