ウィンドウ・モード用のウィンドウを生成する

ウィンドウ・モードでゲーム・アプリケーションを作る場合、ウィンドウの生成に注意しなければならない。ここではウィンドウ・モード用のウィンドウを生成する方法を紹介する。

ウィンドウ・モードにおけるウィンドウのサイズ

ウィンドウ・モードでゲーム・アプリケーションを作成する場合、ウィンドウの生成には注意しなければならない。
Windowsの各ウィンドウには、タイトルバーやウィンドウ枠が付くため、ゲーム画面などが表示されるウィンドウのクライアント領域を特定のサイズにするには、ウィンドウ全体のサイズをウィンドウ枠などの分も考慮して決定しなければならない。しかも、タイトルバーやウィンドウ枠のサイズはユーザの設定によって変更されていることがあるため、固定値を指定することはできない

よって、ウィンドウ・モード用のウィンドウを生成するには、クライアント領域が常に同じ大きさになるようにプログラミングしなければならない。

ウィンドウ・モード用のウィンドウの生成

では実際に、フルスクリーン・モード用のウィンドウを、ウィンドウ・モード用のウィンドウに改造する方法を紹介する。
次のような手順で、ウィンドウ・モード用のウィンドウを生成する。

  1. とりあえずのウィンドウを生成し、そこからタイトルバーやウィンドウ枠のサイズを取得する。
  2. 必要なウィンドウ・サイズを計算し、計算した幅と高さをウィンドウにセットする。

この手順どおりにウィンドウを生成するよう、プログラムを改造する。

まず、CreateWindow関数にCW_USEDEFAULT(デフォルト)を指定して実行する。なお、ウィンドウ・モード用のウィンドウなので、ウィンドウスタイルにはポップアップ・ウィンドウではなく普通のウィンドウスタイルを指定する。

// ウィンドウクラスの登録ができたので、ウィンドウを生成する
hWnd = CreateWindow(
    szWinName,             // ウィンドウクラスの名前
    szWinTitle,            // ウィンドウタイトル
    WS_OVERLAPPEDWINDOW,   // ウィンドウスタイル
    CW_USEDEFAULT,         // ウィンドウの左角X座標
    CW_USEDEFAULT,         // ウィンドウの左角Y座標
    CW_USEDEFAULT,         // ウィンドウの幅
    CW_USEDEFAULT,         // ウィンドウの高さ
    NULL,                  // 親ウィンドウ(なし)
    NULL,                  // メニュー(なし)
    hThisInst,             // このプログラムのインスタンスのハンドル
    NULL                   // 追加引数(なし)
);

次に、生成したウィンドウの全体のサイズとクライアント領域のサイズを取得し、そこから、必要なウィンドウのサイズを計算する。
ウィンドウの全体のサイズは「GetWindowRect API関数」、クライアント領域のサイズは「GetClientRect API関数」によってそれぞれ四隅の座標が取得できるので、そこからクライアント領域以外に必要なサイズ(タイトルバーやウィンドウ枠の分)を計算することができる。

RECT wRect, cRect;  // ウィンドウ全体の矩形、クライアント領域の矩形
int ww, wh;         // ウィンドウ全体の幅、高さ
int cw, ch;         // クライアント領域の幅、高さ

// ウィンドウ全体の幅・高さを計算
GetWindowRect(hWnd, &wRect);
ww = wRect.right - wRect.left;
wh = wRect.bottom - wRect.top;
// クライアント領域の幅・高さを計算
GetClientRect(hWnd, &cRect);
cw = cRect.right - cRect.left;
ch = cRect.bottom - cRect.top;
// クライアント領域以外に必要なサイズを計算
ww = ww - cw;
wh = wh - ch;
// ウィンドウ全体に必要なサイズを計算
ww = SCREEN_WIDTH + ww;
wh = SCREEN_HEIGHT + wh;

タイトルバーやウィンドウ枠のサイズを考慮した正しいウィンドウの幅と高さを求めることができた。あとは生成したウィンドウに正しい幅と高さをセットすればよい。

// 計算した幅と高さをウィンドウに設定
SetWindowPos(hWnd, HWND_TOP, 0, 0, ww, wh, SWP_NOMOVE);

※フルスクリーン・モード用に作成したプログラムに上記修正を行い、ウィンドウ・モード用のウィンドウが表示されるかどうかを確認する。

どちらのモードを使うべき?

このように、ウィンドウ・モードでゲームを作成する場合はちょっと?面倒である。ではフルスクリーン・モードとウィンドウ・モードのどちらでゲームを開発すればよいのだろうか?

DirectXはバージョン8以降、2Dの技術は見捨てられ、3Dのみを考えられて作られている。そして、描画機能はフルスクリーン・モードよりウィンドウ・モードのほうが早い(DirectX7までは、フルスクリーン・モードのほうが早かった)。
しかし、この授業はスチューデントゲーム大賞に応募できるゲームを作成するために実施されている。そして、東京ゲームショウに出展している他校のゲームを見ても、フルスクリーン・モードで開発されている。
よって、とりあえずはフルスクリーン・モードで開発すればいいのではないだろうか?フルスクリーン・モードでコマ落ちすることなく動くようなゲームが作れれば、ウィンドウ・モードに切り替えても問題なく動くはずだからである。
また、ゲームはフルスクリーン・モードで表示すると臨調感が増す。その分、グラフィックには注意を払わなければいけないが・・・

しかし、最初からフルスクリーン・モードで作り始めると、デバッグ表示などが見えないという弊害もある。そこで、開発中はウィンドウ・モードを使い、ゲームがある程度完成してからフルスクリーン・モードを使うというのが一般的らしい。
開発中と完成後でモードを切り替えたい場合、例えばdefine文で値をセットし、その値によってフルスクリーン・モードのウィンドウを生成するか、ウィンドウモードのウィンドウを生成するかを切り替えればよいだろう。

授業資料では、特に指定の無い限り、フルスクリーン・モードで開発することにする。


BACK(フルスクリーン・モード用のウィンドウを生成する) BACK(ウィンドウ・モードを切り替える)