フレーム制御

フレームの制御部分の実装をクラス化してみた。

// -- FrameControl.h --
#pragma once

#include <windows.h>

namespace ddp {

    class FrameControl {
    private:
        int m_fps;
        int m_frameCount;
        int m_fpsCount;
        TCHAR m_fpsStr[64]; // ここちょっと微妙
        DWORD m_beforeTime;
        DWORD m_fpsTime;
        float m_frameTime;
    public:
        FrameControl (DWORD fps = 60);
        ~FrameControl ();
        void Start();
        void End();
        int GetFPS() const;
        const TCHAR* GetFPS(const TCHAR* format);
    };
};
// -- FrameControl.cpp --
#include "FrameControl.h"

namespace ddp {
    FrameControl::FrameControl (DWORD fps) {
        // デフォルトでは一秒間(千ミリ秒)に60フレーム
        m_frameTime = 1000.0f / fps;
        m_frameCount = 0;
        m_fpsCount = 0;
        m_fpsTime = 0;
        timeBeginPeriod(1);
    }

    FrameControl::~FrameControl () {
        timeEndPeriod(1);
    }

    void FrameControl::Start () {
        m_beforeTime = timeGetTime();
        m_frameCount++;
    }

    void FrameControl::End () {
        while ( timeGetTime() - m_beforeTime < m_frameTime ) {
            Sleep(1);
        }

        if(timeGetTime() - m_fpsTime >= 1000){
            m_fpsTime = timeGetTime();
            m_fpsCount = m_frameCount;
            m_frameCount = 0;
        }
    }

    int FrameControl::GetFPS() const {
        return m_fpsCount;
    }

    // 文字列形式で取れたら便利だと思ったんだけどこれやっぱ微妙かも
    const TCHAR* FrameControl::GetFPS(const TCHAR* format) {
        wsprintf(m_fpsStr,format,m_fpsCount);
        return m_fpsStr;
    }

};

使い方は以下

void GameMain::MainLoop() {
    m_fc.Start(); // フレーム制御前処理

    Update();
    if ( SUCCEEDED(m_dxc->DrawStart()) ) {
        Draw();
        m_dxc->DrawEnd();
    }

    m_fc.End(); // フレーム制御後処理。ここでwaitが入る
}

現在のFPSを取得するGetFPS関数を用意したんだけど、文字列を返す方はちょっと微妙かも。std::stringの方が色々と便利だとは思うんだけどwsprintfと組み合わせるのがどうもうまくできなかったのでやめた。うーん、やっぱ文字関連は扱いが難しい。