DirectX 8.0 入門


~ゲームでも作るか~




■はじめに

本来は NURBS を解説するところですが、 このままでは何時終わるか分からないので、実際にプログラムを組む路線に変更します。
っていうか、俺が使わないから上手く解説できん。

2001年現在のゲームプログラムの主流は。DirectX であることは、疑いがないと思います。 DirectX は、8.0 になってから、初期化が簡単になり、プログラム作りが楽になりました。 と、いっても、初心者には、まだまだ作るのが大変です。 とりあえず、(同人で売れるくらいの?)ゲームを一本作る程度の仕事及び、 いろいろな Tips を目指して、作りたいと思います。

■はじめの一歩

とりあえず、下のソースをダウンしてください。Visual C++ 6.0 のプロジェクトになっています。

かなり基本的なウィンドウズのプログラムです。ウィンドウしか表示しません
では、内容を見てみましょう。 Windows のプログラムは WinMain から始まります。
大まかな流れは、次のようになります。

ウィンドウの作成
  ↓←─────────────────┐
メインループ                            │
  ├──────┬────┐            │
  ↓            ↓        ↓            │
終了イベント   描画 キーなどのイベント  │
  │            └────┴──────┘
  ↓
確保したメモリの開放
  ↓
終了

まず、ウィンドウを作ります。 この処理はほとんど決まっているので、みんな一度作ったらそれをコピーして使っていると思います。
次にメインループがぐるぐる回っています。
ウィンドウズは(一度は聞いたことがあると思いますが)、イベント駆動型の取り扱いに適したOSです。 『キーが押された』、『マウスがクリックされた』等の処理が発生したときに、『イベント』が発生するので、 プログラマーは、それぞれのイベントに適した処理をします。
ウィンドウの左上の×ボタンを押した時は、終了のイベントが発生します。 終了イベントの発生を監視して、プログラムで使ったメモリなどの後片付けをした後に、 プログラムを終了します。 この後片付けを忘れると、メモリの空き領域が減っていき、 いき過ぎるとウィンドウズが正常に動作しないようになります。

では、一気にはじめの関数である WinMain を見てみましょう。

static bool s_end;		// 終了フラグ

int PASCAL WinMain(HINSTANCE hInst,HINSTANCE hPrev,char *CmdLine,int CmdShow)
{
    s_end = 0;
    
    // ★★★★★ ウインドウの作成
    RECT    rect;
    SetRect(&rect, 0, 0, WIDTH, HEIGHT);
    DWORD   style = (FULLSCREEN) ? WS_POPUP : WS_CAPTION|WS_SYSMENU|WS_BORDER|WS_MINIMIZEBOX;
    AdjustWindowRect(&rect, style, FALSE);    // ウィンドウスタイルを設定したときの、ウィンドウの大きさを調べる
    int width  = rect.right - rect.left;
    int height = rect.bottom - rect.top;    
    
    WNDCLASS wc;
    ZeroMemory(&wc, sizeof(WNDCLASS));
    wc.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.hCursor            = LoadCursor(NULL,IDC_ARROW);
    wc.hInstance        = hInst;
    wc.lpfnWndProc        = MsgProc;
    wc.lpszClassName    = CAPTION;
    if(RegisterClass(&wc) == 0) return 0; //ウィンドウ作成に使用できる新しいウィンドウクラスを作成する。
    
    HWND hWnd = CreateWindow(CAPTION        // 登録されているクラス名
                            ,CAPTION        // ウィンドウ名
                            ,style            // ウィンドウスタイル
                            ,CW_USEDEFAULT    // ウィンドウの横方向の位置
                            ,CW_USEDEFAULT    // ウィンドウの縦方向の位置
                            ,width            // ウィンドウの幅
                            ,height            // ウィンドウの高さ
                            ,NULL            // 親ウィンドウまたはオーナーウィンドウのハンドル
                            ,NULL            // メニューハンドルまたは子ウィンドウ ID
                            ,hInst            // アプリケーションインスタンスのハンドル
                            ,NULL            // ウィンドウ作成データ
                            );
    if(hWnd == NULL) return 0;
    
    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);

    // ★★★★★ メインループ
    MSG msg;
    while (!s_end)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
            // メッセージの処理
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }else{
            // メッセージが来ない時(後々、描画系の処理が入る)
        }
    }
    
    // ★★★★★ 終了
    return 0;
}

なお、WIDTH, HEIGHT, FULLSCREEN, CAPTION は main.h で定義しています。 これは、今後ゲームを作ることを考えると、解像度は変化しないと考え、このような方式にしました。
ない様ですが、AdjustWindowRect で、ウィンドウのサイズを計算し、RegisterClass で、背景色などの設定をし、 CreateWindow で、ウィンドウを作成します。
メインループでは、s_end が true になるのを待って、ループを回します。 PeekMessage がイベントを拾う関数で、メッセージがおきたら、TranslateMessage, DispatchMessage で 処理をします。 実際には、その中で wc.lpfnWndProc の MsgProc が呼ばれます。 まぁ、そんなもんだと思ってください。
MsgProc は、下の関数で、WM_CLOSE のイベント(もしくは WM_KEYDOWN のコマンド)で、 s_end を true にして、終了を促します。
つまり、このプログラムは、×ボタンを押すか、キーボードのどこかを押すと終了します。

LRESULT CALLBACK MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    switch (msg){
    case WM_KEYDOWN:                // 何かキーが押された
    case WM_CLOSE:                  // ×ボタンを押した
        s_end = true;
        return 1;
        break;
    default:
        break;
    }
    return DefWindowProc(hWnd,msg,wParam,lParam);
}

あと、今回は特にメモリの確保をしていないので、後片付けですることはありませんでした。

このプログラムは、一般のウィンドウズプログラムで、Direct X はまだ出てきません。
次から、いよいよ Direct X のプログラムに入ろうと思います。





もどる

imagire@gmail.com