Skip to main content

付録2 DxLibテンプレート

付録2 DxLibゲームテンプレート

このページでは、新しいDxLib用プロジェクトを作成し、保存しておいたプロパティシートを読み込んでから、ゲーム制作の土台となるテンプレートを作ります。

あらかじめ、前の付録で次の2つのプロパティシートを作成しておいてください。

DxLib_Debug.props
DxLib_Release.props

このテンプレートでは、次の4つの関数を使ってゲームを作ります。

Initialize();
Update();
Draw();
DeltaTime();
  • Initialize():ゲーム開始時に1回だけ実行する
  • Update():入力確認とゲームの更新を行う
  • Draw():画面を描画する
  • DeltaTime()Update()1回分の経過時間を秒で返す

このページでは、次の順番で作業します。

新しいプロジェクトを作る
        ↓
main.cppを追加する
        ↓
文字セットを設定する
        ↓
Debug用とRelease用のプロパティシートを読み込む
        ↓
ゲームテンプレートを入力する
        ↓
実行する

1.新しいプロジェクトを作る

Visual Studio上部のメニューから、次の順番で選択します。

ファイル
  └─ 新規作成
      └─ プロジェクト/ソリューション

「新しいプロジェクトの作成」画面で、次の項目を選択します。

Windows デスクトップ ウィザード

プロジェクト名は、作るゲームに合わせて決めてください。

このページでは、例として次の名前を使用します。

DxLibGame

保存場所には、自分の作業フォルダーを指定します。

「ソリューションとプロジェクトを同じディレクトリに配置する」にチェックを付け、「作成」をクリックします。

「Windows デスクトップ プロジェクト」の設定画面では、次のように設定します。

項目設定内容
アプリケーションの種類デスクトップ アプリケーション(.exe)
空のプロジェクトチェックを付ける

設定できたら、「OK」をクリックします。

Visual Studio上部のプラットフォームが、次のようになっていることも確認してください。

x64

2.main.cppを追加する

ソリューションエクスプローラーの「ソースファイル」を右クリックし、次の順番で選択します。

追加
  └─ 新しい項目

「C++ファイル(.cpp)」を選択し、名前を次のようにします。

main.cpp

「追加」をクリックします。


3.main.cppをUTF-8で保存する

コードエディター右下に表示されている文字コードをクリックします。

表示されたメニューから「エンコードで保存」を選択し、次のエンコードを指定します。

Unicode(UTF-8 署名付き)- コードページ 65001

「OK」をクリックして保存します。

UTF-8は、main.cppをファイルへ保存するときの文字コードです。次に設定する「文字セット」とは別の設定です。


4.文字セットを設定する

プロパティシートの設定画面には、「文字セット」の項目が表示されません。

これはVisual Studioの仕様です。この資料では、文字セットをプロパティシートへ無理に保存せず、新しいプロジェクトを作るたびにプロジェクト側へ設定します。

ソリューションエクスプローラーで、プロジェクト名の「DxLibGame」を右クリックし、「プロパティ」を選択します。

プロパティ画面の上部を、次のように設定します。

項目設定内容
構成すべての構成
プラットフォームすべてのプラットフォーム

左側から、次の項目を開きます。

構成プロパティ
  └─ 詳細
      └─ 文字セット

「文字セット」を、次のように変更します。

マルチ バイト文字セットを使用する

「適用」をクリックしてから、「OK」をクリックします。

「すべての構成」を選択して設定したため、DebugとReleaseの両方に同じ文字セットが設定されます。


5.プロパティ マネージャーを開く

Visual Studio上部のメニューから、次の順番で選択します。

表示
  └─ その他のウィンドウ
      └─ プロパティ マネージャー

プロパティ マネージャーには、構成とプラットフォームの組み合わせが表示されます。

DxLibGame
├─ Debug | Win32
├─ Debug | x64
├─ Release | Win32
└─ Release | x64

このページでは、次の2か所へプロパティシートを追加します。

Debug | x64
Release | x64

6.Debug用プロパティシートを読み込む

プロパティ マネージャーの「Debug | x64」を右クリックし、「既存のプロパティ シートの追加」を選択します。

自分のPropertySheetsフォルダーを開き、次のファイルを選択します。

DxLib_Debug.props

追加後、次のように表示されれば成功です。

Debug | x64
└─ DxLib_Debug

DxLib_Debug.propsから、次の設定が読み込まれます。

  • DxLibの追加のインクルードディレクトリ
  • DxLibの追加のライブラリディレクトリ
  • Debug用ランタイムライブラリの/MTd

7.Release用プロパティシートを読み込む

プロパティ マネージャーの「Release | x64」を右クリックし、「既存のプロパティ シートの追加」を選択します。

自分のPropertySheetsフォルダーを開き、次のファイルを選択します。

DxLib_Release.props

追加後、次のように表示されれば成功です。

Release | x64
└─ DxLib_Release

DxLib_Release.propsから、次の設定が読み込まれます。

  • DxLibの追加のインクルードディレクトリ
  • DxLibの追加のライブラリディレクトリ
  • Release用ランタイムライブラリの/MT

DebugとReleaseには、それぞれ対応するプロパティシートを読み込んでください。

Debug   → DxLib_Debug.props
Release → DxLib_Release.props

8.プロパティシートの読み込みを確認する

プロパティ マネージャーが、次のようになっていることを確認します。

DxLibGame
├─ Debug | x64
│  └─ DxLib_Debug
└─ Release | x64
   └─ DxLib_Release

これで、新しいプロジェクトへ次の設定ができました。

設定設定した場所
文字セットプロジェクト本体
DxLibのインクルードパスプロパティシート
DxLibのライブラリパスプロパティシート
Debug用ランタイムライブラリDxLib_Debug.props
Release用ランタイムライブラリDxLib_Release.props

ここまで完了したら、プロパティ マネージャーを閉じてmain.cppへ戻ります。


やっとプログラム説明

9.ゲームループ

ゲームは、入力・更新・描画を繰り返して動いています。

Initializeを1回実行する
        ↓
実際に経過した時間を測る
        ↓
1/60秒分たまっていればUpdateを実行する
        ↓
Drawで画面を描画する
        ↓
最初へ戻る

Update()は、ゲーム内部の時間が1/60秒進むたびに実行されます。

処理が遅れて1/60秒が複数回分たまっている場合は、Draw()を行う前にUpdate()を複数回実行します。


2.10.フレームレート

このテンプレートでは、ゲーム内部の更新回数を1秒間に60回へ固定します。

const int UPDATE_FPS = 60;
const double FIXED_DELTA_TIME = 1.0 / UPDATE_FPS;

DeltaTime()が返す値は、次のとおりです。

1 ÷ 60 = 約0.016666秒

したがって、Update()の中で次のように書くと、1秒間にspeedだけ移動します。

position += speed * DeltaTime();

このテンプレートで固定しているのは、Update()によるゲーム内部の更新間隔です。

Draw()の実行回数は、モニターのリフレッシュレートや処理速度によって変わることがあります。


3.11.テンプレート

main.cppへ、次のプログラムを入力します。

#include "DxLib.h"

// 画面の大きさ
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;

// ゲーム内部を1秒間に更新する回数
const int UPDATE_FPS = 60;

// Update1回分の時間
const double FIXED_DELTA_TIME = 1.0 / UPDATE_FPS;

// 長時間処理が止まった場合に、
// 一度に処理する経過時間の上限
const double MAX_FRAME_TIME = 0.25;

// ゲーム開始時に1回だけ実行する
void Initialize(void)
{
    // 初期化処理を書く
}

// 入力確認とゲームの更新を行う
void Update(void)
{
    // キーボードやマウスの入力処理を書く

    // ゲームの更新処理を書く
}

// ゲーム画面を描画する
void Draw(void)
{
    // 描画処理を書く
}

// Update1回分の時間を秒で返す
double DeltaTime(void)
{
    return FIXED_DELTA_TIME;
}

int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
    LONGLONG previousTime;
    double accumulator;

    // ウィンドウモードで起動する
    ChangeWindowMode(TRUE);

    // 画面の大きさを設定する
    SetGraphMode(
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        32);

    // ScreenFlipで垂直同期を待つ
    SetWaitVSyncFlag(TRUE);

    // DxLibを初期化する
    if (DxLib_Init() == -1)
    {
        return -1;
    }

    // 描画先を裏画面にする
    SetDrawScreen(DX_SCREEN_BACK);

    // ゲームを初期化する
    Initialize();

    // 時間計測を開始する
    previousTime = GetNowHiPerformanceCount();

    // まだUpdateで処理していない時間
    accumulator = 0.0;

    // ゲームループ
    while (ProcessMessage() == 0)
    {
        LONGLONG currentTime;
        double frameTime;

        // ESCキーが押されたら終了する
        if (CheckHitKey(KEY_INPUT_ESCAPE) != 0)
        {
            break;
        }

        // 現在時刻を取得する
        currentTime = GetNowHiPerformanceCount();

        // 前回から実際に経過した時間を秒で求める
        frameTime =
            (currentTime - previousTime) / 1000000.0;

        // 次の計測に備えて現在時刻を保存する
        previousTime = currentTime;

        // 長時間止まった場合は、処理する時間を制限する
        if (frameTime > MAX_FRAME_TIME)
        {
            frameTime = MAX_FRAME_TIME;
        }

        // 実際に経過した時間をためる
        accumulator += frameTime;

        // 1/60秒以上たまっている間、ゲームを更新する
        while (accumulator >= DeltaTime())
        {
            Update();

            // Updateで処理した時間を引く
            accumulator -= DeltaTime();
        }

        // 裏画面を黒で消す
        ClearDrawScreen();

        // ゲーム画面を描画する
        Draw();

        // 裏画面を表画面へ表示する
        ScreenFlip();
    }

    // DxLibを終了する
    DxLib_End();

    return 0;
}

入力できたら、次のキーで保存します。

Ctrl + S

4.12.Debugで実行確認する

Visual Studio上部を、次のように設定します。

項目設定内容
構成Debug
ラットフォームx64

次のキーを押して、デバッラムをなしで実行します。

Ctrl + F5

次のことを確認してください。

  • 800×600の黒いウィンドウが表示される
  • ウィンドウがすぐに閉じない
  • ESCキーを押すと終了する
  • ウィンドウ右上の閉じるボタンでも終了できる

13.Releaseでもビルドする

Visual Studio上部を、次のように変更します。

項目設定内容
構成Release
プラットフォームx64

次のキーを押してビルドします。

Ctrl + Shift + B

出力欄に、次のような内容が表示されれば成功です。

ビルド: 1 正常終了、0 失敗

DebugとReleaseの両方でビルドできれば、2つのプロパティシートは正しく読み込まれています。


14.次のプロジェクトから行う作業

プロパティシートは、次に作るゲームでもそのまま使用できます。

新しいDxLib用プロジェクトを作るときは、次の作業を行います。

新しいプロジェクトを作る
        ↓
main.cppを追加する
        ↓
main.cppをUTF-8で保存する
        ↓
文字セットをマルチバイトへ変更する
        ↓
Debug | x64へDxLib_Debug.propsを追加する
        ↓
Release | x64へDxLib_Release.propsを追加する
        ↓
ゲームテンプレートを入力する

黒いウィンドウが表示され、DebugとReleaseの両方でビルドできれば、ゲーム制作の準備は完了です。

一回なれちゃうとパパっとできるようになるので、それまでは修行!