Skip to main content

付録2 DxLibテンプレート

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

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

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

1.ゲームループ

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

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

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

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


2.フレームレート

このテンプレートでは、ゲーム内部の更新回数を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.テンプレート

#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;
}

4.実行確認

プログラムを実行し、次のことを確認してください。

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

黒いウィンドウが表示されれば、ゲーム制作の準備は完了です。