ゆとりーなの日記

日記的な事を書いて行くと思はれる

なんかつい最近に失恋した気がするけど既に脳みそはプリプロセッサによってC++に置換され始めている

後輩がゲーム製作(プログラミング部門)の進捗状況を話してくれました。つい昨日の事です。何やらウィンドウの生成までは行けたらしいのですが、なにやらメイン関数に全て詰め込んで書いてしまったらしく、つい私の十八番であるdisりが出てしまいました。

#include <windows.h>

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    const LPCSTR window_class_name("BASE");
    const WNDCLASSEX window_class = {
        sizeof(WNDCLASSEX),
        CS_HREDRAW | CS_VREDRAW,
        DefWindowProc,
        0,
        0,
        GetModuleHandle(nullptr),
        static_cast<HICON>(LoadImage(nullptr, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 32, 32, LR_DEFAULTSIZE | LR_SHARED)),
	static_cast<HCURSOR>(LoadImage(nullptr, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED)),
	static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)),
	nullptr,
	window_class_name,
	nullptr
    };
    if (!RegisterClassEx(&window_class)) {
        return 0;
    }
    const HWND window_handle(CreateWindow(window_class_name, "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, GetModuleHandle(nullptr), nullptr));
    if (!window_handle) {
        return 0;
    }
    ShowWindow(window_handle, SW_RESTORE);
    MSG message;
    for (;;) {
        const BOOL result(GetMessage(&message, nullptr, 0, 0));
        if (!(result && ~result)) {
            break;
        }
        TranslateMessage(&message);
        DispatchMessage(&message);
    }
    return message.wParam;
}

メイン関数にウィンドウ生成コード詰め込むっていうのは要約するとこういうことです。このままではウィンドウ閉じても終了しないよというツッコミはここでは本質ではないので無視します。要はメイン関数に全部突っ込むと見難いよということが言いたいわけです。
さて、disるだけでは後輩に対して示しがつかないので代替案を示さなければいけません。現場で出た案としてはksk氏から「クラスに纏めたら」的なサムシングを提案していましたが、ゲームに於いてこの作戦が有効であるかどうかは実は微妙な所です。
先ず、ウィンドウを管理するクラスを作ることが非常に面倒なことが挙げられます。ウィンドウプロシージャと呼ばれるものを、メンバ関数的に扱うためには色々と複雑なコードが必要となります。staticメンバ関数にすれば一発で解決しますがそれだとインスタンス毎にプロシージャを分割する的なことが出来ません。この辺日本語とか用語が合ってるか怪しいですが気にせず先に進みます。手間をかけて各インスタンス毎にプロシージャを分割する的なことをやってもゲームに於いてはウィンドウは実は一個しか作らないということが殆どな気がするので意味がないのではというジレンマに陥ります。

#include <windows.h>

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    Application application;
    Window window;
    window.show();
    return application.run();
}

そこでクラスにはせずに名前空間で括ったモジュール的な物にした方がいいのではないかという案が出てきます。そこではウィンドウを管理するシングルトンクラス等が台頭してくることになるでしょう。C++0x以降static変数のスレッドに対する安全性が初期化に関しては格段に上がっているのでシングルトンが作り易くなったのも相まって、今のところゲームではこの案が一番ましなのかなと思っていたりします。

#include <windows.h>

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    window::show();
    return application::run();
}