Skip to content
第13回 新作プロジェクトとゲームの土台

2 / 4 DXライブラリのライフタイムとスコープ制御

このステップの目的

main.cpp におけるDXライブラリの初期化と終了処理の対応関係を正しく構築し、RAIIを用いてリソース解放の順序を安全に制御します。

画面設定とフレームレートの集約

画面解像度や目標フレームレートは、複数のクラスから参照される共通の設定値です。これらをマジックナンバーとして各所に散らさず、ApplicationConfig.h に一元管理します。

ApplicationConfig.hcpp
namespace dxgame::config
{
    inline constexpr int ScreenWidth = 640;
    inline constexpr int ScreenHeight = 480;
    inline constexpr int FrameRate = 60;

    // 1フレームあたりの経過時間(秒):約0.01667秒
    inline constexpr float DeltaTime = 1.0f / FrameRate;

    // 1フレームあたりの目標ミリ秒:約16.667ms
    inline constexpr double FrameMilliseconds = 1000.0 / FrameRate;
}

初期化と終了処理の厳密な対応

ゲームの起動エントリーポイントである main.cpp では、DXライブラリの初期化手順を決められた順序で実行します。

main.cppcpp
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    // ウィンドウモードの設定と解像度の指定
    ChangeWindowMode(TRUE);
    SetGraphMode(dxgame::config::ScreenWidth, dxgame::config::ScreenHeight, 32);

    // DXライブラリの初期化
    if (DxLib_Init() == -1)
    {
        // 初期化に失敗した場合は、DXライブラリが開始されていないためDxLib_Endは呼ばずに終了する
        return -1;
    }

    // 描画先を裏画面(バックバッファ)に設定する
    SetDrawScreen(DX_SCREEN_BACK);

    int result = 0;
    {
        // 波括弧によるスコープを作る
        dxgame::platformer::Game game;
        if (!game.Initialize())
        {
            result = -1;
        }
        else
        {
            game.MainLoop();
        }
    } // ここで game のデストラクタが実行され、画像や音声が確実に解放される
    } // ここで game のデストラクタが実行され、画像や音声が自動的に解放される

    // すべてのリソースが解放された安全な状態でDXライブラリを終了する
    DxLib_End();
    return result;
}

波括弧(スコープ)によるRAIIの保証

上記のコードで重要な点は、Game game; が意図的に波括弧 { } の内側に配置されていることです。

もし波括弧を作らずに WinMain() の直下に game を宣言してしまうと、関数の末尾で DxLib_End() が呼ばれたgame のデストラクタが実行されることになります。
そうなると、ImageManagerSoundManager がデストラクタで DeleteGraph()DeleteSoundMem() を呼ぼうとしたとき、すでにDXライブラリ本体が終了してしまっているため、エラーや未定義動作を引き起こします。

波括弧を設けてスコープを限定することにより、「必ず DxLib_End() が呼ばれる前に、すべてのゲーム内リソースが破棄される」 という安全な順序が言語仕様(RAII)に基づいて保証されます。

チェックリスト
  • DxLib_Init() が失敗した際に、不正な DxLib_End() を呼ばずに終了するガードがある
  • バックバッファ描画(SetDrawScreen(DX_SCREEN_BACK))が設定されている
  • Game クラスが波括弧スコープ内で生成され、DxLib_End より前に確実に破棄される理由を説明できる

ゲームプログラミング実践