テストアプリケーション用テンプレートを作った
テスト用アプリケーションを作成しやすいように、テンプレート的なものを作りました。
アプリケーションクラスの作成
ウィンドウ作成などのWin32APIの面倒な処理をこのクラスが担当します。
一応、他プラットフォームでも対応できるようにインターフェイスクラスとして宣言しています。
KEY_CODE は列挙型で、別のヘッダーファイルで宣言されています。
AppMain関数がメインエントリポイントになります。
App.hpp
#pragma once struct Position2D { s32 x; s32 y; }; struct Size2D { u32 width; u32 height; }; // コールバック登録用 struct AppCallbacks { // リサイズ void(*pOnResize)(const Size2D& newSize, void* pUser); void* pOnResizeUser; // キーダウン void(*pOnKeyDown)(KEY_CODE key, void* pUser); void* pOnKeyDownUser; // キーアップ void(*pOnKeyUp)(KEY_CODE key, void* pUser); void* pOnKeyUpUser; // マウスキーダウン void(*pOnMouseKeyDown)(const Position2D& position, MOUSE_BUTTON button, void* pUser); void* pOnMouseKeyDownUser; // マウスキーアップ void(*pOnMouseKeyUp)(const Position2D& position, MOUSE_BUTTON button, void* pUser); void* pOnMouseKeyUpUser; // マウスホイール void(*pOnMouseWheel)(const Position2D& position, s32 delta, void* pUser); void* pOnMouseWheelUser; }; // アプリケーションインターフェイス class IApp { public: virtual ~IApp() = default; // コールバックを登録 virtual void SetAppCallbacks(const AppCallbacks& callbacks) = 0; // true の間、メインループを実行 virtual bool IsLoop() const = 0; // アプリケーションを終了 virtual void PostQuit() = 0; // クライアント領域のサイズを取得 virtual Size2D GetClientSize() const = 0; // ウィンドウハンドルを取得 virtual void* GetWindowHandle() const = 0; // メッセージボックスを表示 virtual void ShowMessageBox(const std::string& message, const std::string& caption) = 0; }; // IApp ファクトリーメソッド bool CreateApp(const Size2D& clientSize, const std::string& title, IApp ** ppOut); // メインエントリポイント void AppMain();
実装例
AppMain.cppではAppMain関数の定義と各種コールバックの登録を行っています。
AppMain関数内でコールバックの登録後、IApp::IsLoop()がtrueの間メインループを実行します。
AppMain.cpp
#define UNUSED(x) (x) // リサイズ void OnResize(const Size2D& newSize, void* pUser) { UNUSED(newSize); UNUSED(pUser); } // キーダウン void OnKeyDown(KEY_CODE key, void* pUser) { IApp* pApp = reinterpret_cast<IApp*>(pUser); if (pApp == nullptr) { return; } if (key == KEY_CODE_ESCAPE) { // Escapeキーで終了 pApp->PostQuit(); } } // キーアップ void OnKeyUp(KEY_CODE key, void* pUser) { UNUSED(key); UNUSED(pUser); } // マウスキーダウン void OnMouseKeyDown(const Position2D& position, MOUSE_BUTTON button, void* pUser) { UNUSED(position); UNUSED(button); UNUSED(pUser); } // マウスキーアップ void OnMouseKeyUp(const Position2D& position, MOUSE_BUTTON button, void* pUser) { UNUSED(position); UNUSED(button); UNUSED(pUser); } // マウスホイール void OnMouseWheel(const Position2D& position, s32 delta, void* pUser) { UNUSED(position); UNUSED(delta); UNUSED(pUser); } // シーン更新処理 void UpdateScene() { } // シーン描画処理 void RenderScene() { } // エントリポイント void AppMain() { IApp* pApp = nullptr; Size2D clientSize = { 640, 480 }; if (!CreateApp(clientSize, "Sample", &pApp)) { return; } // コールバックの設定 AppCallbacks callbacks = { 0 }; // リサイズ callbacks.pOnResize = OnResize; callbacks.pOnResizeUser = pApp; // キーダウン callbacks.pOnKeyDown = OnKeyDown; callbacks.pOnKeyDownUser = pApp; // キーアップ callbacks.pOnKeyUp = OnKeyUp; callbacks.pOnKeyUpUser = pApp; // マウスキーダウン callbacks.pOnMouseKeyDown = OnMouseKeyDown; callbacks.pOnMouseKeyDownUser = pApp; // マウスキーアップ callbacks.pOnMouseKeyUp = OnMouseKeyUp; callbacks.pOnMouseKeyUpUser = pApp; // マウスホイール callbacks.pOnMouseWheel = OnMouseWheel; callbacks.pOnMouseWheelUser = pApp; pApp->SetAppCallbacks(callbacks); // メインループ while (pApp->IsLoop()) { UpdateScene(); RenderScene(); } delete pApp; }
できるだけ使いやすく作ったつもりですが、もう少しシンプルにできたかもしれません。
コードはGitHubにて公開していますので、ご自由にお使いください。