ローテク:ローテクです.
ローテクのFPS講座第二回目.
今回は前回のプログラムの解説をしたいと思います.
えーと,あの二人は…
ねここ :こんにちはなのですよー
ショータ:こんにちは
ローテク:おぉこんなところに.こんにちはー.
ねここ :しっかりお勉強してきたのですよ
これであんなこともこんなこともばっちりなのです
ローテク:おぉー.(さすが電子生命体だけあって相性はいいみたいだなぁ)
ショータ:ところでずいぶんゆっくりすすんでるけど
この講座おわるの?
ローテク:すすみ方ですが,最初はゆっくりやっていこうかなと思っています.
けど回が進むごとに進行速度が速くなっていくと思いますので
がんばってついて行ってください.
ねここ :いきなりきびしいこといいますね
ローテク:まぁだんだん慣れていくと思いますし,そんなぶっ飛んだ進み方は
しないようにします.
では早速本題ということで前回すっ飛ばしたプログラムの解説からです.
#pragma once //ライブラリのインクルード #pragma comment(lib, "d3dxof.lib") #pragma comment(lib, "dxguid.lib") #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "winmm.lib") #ifdef _DEBUG #pragma comment(lib, "d3dx9d.lib") #else #pragma comment(lib, "d3dx9.lib") #endif
ねここ :アタシのよんだ本にはこんなこと書いていなかったのですよ.
ローテク:これはVC++特有の記述です.これは何をやっているかというと,
このプログラムを実行するのに必要なライブラリを読み込むための
記述です.プロパティからも設定できるのですがこっちの方が
便利だと思います.
#define _CRT_SECURE_NO_WARNINGS #include <windows.h> #include <d3dx9.h>
ねここ :これはみたことあるですよ.
_CRT_SECURE_NO_WARNINGSを定義してその後に
外部ファイルをよみこんでいるのですよー
でも_CRT_SECURE_NO_WARNINGSってなんなのですか
ローテク:_CRT_SECURE_NO_WARNINGSというのは
マイクロソフトが用意した安全版の関数があるにもかかわらず
その関数を使っていないときに起こる警告を消すための
お呪いです.本当は安全版を使った方がいいのでしょうけど,
汎用性が減りますので. そのほかはその通りです.
ショータ:DirectX使う時点で汎用性も何もないきがするけどね
ローテク:まぁそれもその通り・・・です.
const wchar_t CLASSNAME[] = L"testprogram"; const wchar_t APPNAME[] = L"Test Program";
ローテク:ただの変数宣言&初期化.
プログラムの名前とクラス名はいろいろなところで使うので
一発で変更が出来るように一番上にまとめておきます.
IDirect3D9 *pD3D = NULL; IDirect3DDevice9 *pD3DDevice = NULL;
ローテク:これはDirectXを使うのに必要なインターフェースを受け取るための変数です.
二つあるのはDirectX用とDirectXデバイス用の二つが必要だからです.
ねここ :DirectX用とDirectXデバイス用?
ショータ:デバイスってビデオボードとか?
ローテク:そんな感じです.DirectXAPIの操作用とビデオボードの操作用で一つずつ.
まぁあまり気にしなくても大丈夫です. では次々.
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg){ case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); }
ローテク:これはウィンドウズから送られてくるメッセージを処理するための関数です.
ねここ :アタシたちにもいろいろなメッセージがとんでくるのですよー
それを受け取ると・・・ふにゃ? おもいだせない
ショータ:意識がとんで何かしゃべっちゃうらしいんだよね
ローテク:毒電波か. まぁそんな感じです.君たちと違ってここで受け取るメッセージは
キーボードが押されたとかマウスが動いたとかそんな感じのメッセージが飛んできます.
ということはキーボードやマウスの受付はここでやればいいということです.
では早速メイン中のメインにうつりましょう.というわけでWinMain関数
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const int dispx = 800; const int dispy = 600;
ローテク:これはウィンドウサイズを指定しているだけですので
特に気にする必要はないと思います.
MSG msg; ZeroMemory(&msg, sizeof(msg));
ねここ :これはMSG型のmsgという変数を作って
中身をからにしているのですよー
WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_CLASSDC; wc.lpfnWndProc = MsgProc; wc.hInstance = hInstance; wc.lpszClassName = CLASSNAME; wc.hCursor = LoadCursor(NULL , IDC_ARROW); if (RegisterClassEx(&wc)==NULL) PostQuitMessage(0); HWND hWnd = CreateWindow(CLASSNAME, APPNAME, WS_OVERLAPPEDWINDOW, 0, 0, dispx, dispy, NULL, NULL, wc.hInstance, NULL); if (hWnd==NULL) PostQuitMessage(0); //ウィンドウサイズ微調整 RECT Rect; GetClientRect(hWnd, &Rect); MoveWindow(hWnd, NULL, NULL, dispx+(dispx-Rect.right), dispy+(dispy-Rect.bottom),false);
ローテク:このブロックはウィンドウを作成して,大きさを整えるプログラムです.
この辺を一つ一つ解説すると面倒ですし,知らなくても毎回だいたい同じになりますので
コピペで大丈夫です!というわけで今回はすっ飛ばします.
ショータ:相変わらずいいかげんだなぁ
ローテク:適切な取捨選択といってもらいたい
ショータ:・・・
ねここ :・・・
D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); //DirectXのインターフェースを取得する 1 pD3D = Direct3DCreate9(D3D_SDK_VERSION); //プレゼンテーションパラメータ(表示の基本設定)を指定 2 d3dpp.BackBufferCount = 0; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; d3dpp.Windowed = true; //ウィンドウモードON d3dpp.BackBufferHeight = dispy; //ウィンドウの高さ d3dpp.BackBufferWidth = dispx; //ウィンドウの幅 d3dpp.hDeviceWindow = hWnd; //ウィンドウのハンドル //ステンシルバッファの有無 d3dpp.EnableAutoDepthStencil = true; //ステンシルバッファのフォーマット d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //バックバッファのフォーマット d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; //必要なパラメータを指定してpD3DDeviceにデバイス用のインターフェースをもらう pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD3DDevice);
ローテク:こんなかんじです
ねここ :こんなかんじといわれましても
最初の2行はさっきのMSG型の変数の初期化とおなじみたいですけど
ローテク:1の部分でDirectXを初期化して使える状態にします.
これは決まり文句ですので説明はなし!.
つぎに2ですけどこれは表示する方法の基本的な部分を指定します.
BackBufferCount,SwapEffect,PresentationIntervalは後ほど説明します.
そのほかはコメントにあるとおりです.
ステンシルバッファとバックバッファのフォーマットも必要なときに説明します.
では残りのおまけ的な部分をみていきましょう.
// Show the window ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd);
ローテク:これはウィンドウを表示するためのコマンドです.
これも今後出てくることはないと思いますので詳しくは説明しません.
// Enter the message loop while( msg.message!=WM_QUIT ){ if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); }else{ pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 190, 255 ), 1.0f, 0 ); pD3DDevice->BeginScene(); pD3DDevice->EndScene(); pD3DDevice->Present( NULL, NULL, NULL, NULL ); } }
ローテク:
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){
TranslateMessage( &msg );
DispatchMessage( &msg );
}
この部分で,メッセージが届いていないかをチェックして,もしメッセージが届いていたら
そのメッセージを処理をするように仕向けます.
ショータ:仕向けるって上の方にあった関数に渡すってこと?
ローテク:そんな感じです.一度に送れるメッセージは一つだけなので,
メッセージがある間ずっとメッセージを渡してあげないと変なことになります.
ウィンドウが動かなくなったり,終了できなくなったり.
ねここ :それはおおごとなのですよ
ローテク:
pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 190, 255 ), 1.0f, 0 );
pD3DDevice->BeginScene();
pD3DDevice->EndScene();
pD3DDevice->Present( NULL, NULL, NULL, NULL );
この部分はClearで画面をまっさらにします.
いろいろ引数がありますけどいろいろいじるのは3番目と4番目ぐらいですね.
3番目でまっさらにする対象を,4番目で何色にするかを指定します.
次にBeginSceneで描画の開始を宣言します.
今回はテストですので何も書かずにEndSceneで描画の終了を宣言して
Presentで画面を書き換えます.
ねここ :描画の開始を宣言したのにPresent…?
ローテク:Presentするまでは実際の描画はメモリ上に行われます
一気に画面全体を更新することでちらつきとかを減らすという仕組みです.
pD3DDevice->Release(); pD3D->Release(); UnregisterClass(CLASSNAME, hInstance); return (int)msg.wParam;
ローテク:これは後かたづけです.
初期化したりもらってきたインターフェースはリリースしましょう.
ショータ:使ったら片づけるってことだね
ねここ :プログラムの解説も終わったことだしアタシたちもさっさとお片づけしてかえるですよ
ローテク:早. まだ大切な物が一つ残ってるのに.
}
ローテク:はいこれ. 閉じかっこ.(・∀・) 「こっか」という人もいますけど
というわけでプログラムの説明終ry あいたっ!!
ねここ :( ・・)-○)) )ローテク)
ショーちゃん,おネーちゃんが待ってるのでさっさとするですよ.
ショータ:そういえば何でこの人名前伏せてるの?
ねここ :伏せててもまわりのひとにはバレバレだと思うのですよ
ローテク:え?なんで?!
ショータ:だってその特徴的な句t
ねここ :ショーちゃん それ以上言ったら後が怖いのですよ
ローテク:え?なんで?なんで.
では次回「クラス化!」お楽しみに?