//------------------------------------------------------------------------------------------------- // 問題番号:Exer006 // 問題内容:キャラクタの移動と当たり判定 // Copyright NKC Game Staff(←自分の名前)  //------------------------------------------------------------------------------------------------- #include #include // WindowsAPIを使用可能にする #include #include // DirectX8ヘッダファイル #include // D3DXヘッダファイル // マクロ #define WINMODE FALSE // ウィンドウモードの指定(TRUE:ウィンドウモード/FALSE:フルスクリーン) #define SCREEN_WIDTH 640 // ウィンドウの幅 #define SCREEN_HEIGHT 480 // ウィンドウの高さ /* ゲームの状態を識別する(フレーム番号) */ #define START_INIT 0 #define START_FRAME 1 #define GAME_INIT 10 #define GAME_FRAME 11 /* 頂点フォーマット(基本形)*/ #define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1) // 構造体の宣言 /* 頂点構造体 */ typedef struct _TLVERTEX { float x, y, z; //位置情報 float rhw; //頂点変換値 D3DCOLOR color; //頂点カラー float tu, tv; //テクスチャ座標 } TLVERTX, *LPTLVERTEX; // プロトタイプ宣言 LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM); // Windows関数 BOOL InitApp(HINSTANCE, int); // ユーザー関数 HRESULT InitDX8(void); // DirectX8初期化処理 void InitRender(void); // 描画の設定 void ReleaseD3D(void); // DirectX8開放処理 void ResetWindow(void); // ウィンドウ再生成処理 BOOL UpdateFrame(void); // ゲームメイン処理 void StartInit(void); // スタート画面初期化処理 void StartFrame(void); // スタート画面処理 void InitVertex(LPTLVERTEX, float, float, float, float, int); // 頂点情報格納 void CreateStartTexture(void); // スタート画面用テクスチャ作成処理 // グローバル変数 HWND hWnd; // ウィンドウハンドル BOOL g_appActive = FALSE; // ウィンドウの状態 char szWinName[] = "Exer006"; // ウィンドウクラス用文字列 char szWinTitle[] = "キャラクタの移動と当たり判定"; // ウィンドウクラス用文字列 LPDIRECT3D8 gl_lpD3d = NULL; // Direct3D8インターフェイス LPDIRECT3DDEVICE8 gl_lpD3ddev = NULL; // Direct3DDevice8インターフェイス D3DPRESENT_PARAMETERS gl_d3dpp; // ディスプレイパラメータ LPDIRECT3DTEXTURE8 gl_Texture1; // テクスチャ・オブジェクト1 LPDIRECT3DTEXTURE8 gl_Texture2; // テクスチャ・オブジェクト2 BYTE g_FrameNo = START_INIT; // フレーム選択用 BYTE gl_KeyTbl[256]; // キーボードの状態を格納 TLVERTX VertexDataTbl1[4]; // キャラクタ1用頂点情報配列 TLVERTX VertexDataTbl2[4]; // キャラクタ2用頂点情報配列 char *gl_szCharFileName1 = "sample1.bmp"; // キャラクタ1用画像ファイル名 char *gl_szCharFileName2 = "sample2.bmp"; // キャラクタ2用画像ファイル名 //------------------------------------------------------------------------------------------------- // メイン関数(エントリーポイント)プログラムはここから始まる //------------------------------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { MSG msg; // メッセージ構造体変数 HRESULT hr; //表示するウィンドウの定義、登録、表示 if ( !InitApp(hThisInst, nWinMode) ) // InitApp関数を呼び出し、 return (FALSE); // 正常に終了すれば次にメッセージループへ // DirectX8の初期化 hr = InitDX8(); if ( FAILED(hr) ) return (FALSE); // 描画の設定 InitRender(); // ゲームループ while ( TRUE ) { // メッセージがあるかどうか if ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { // メッセージを取得し、WM_QUITかどうか if ( !GetMessage(&msg, NULL, 0, 0) ) break; TranslateMessage(&msg); //キーボード利用を可能にする DispatchMessage(&msg); //制御をWindowsに戻す } else if ( g_appActive ) { // ゲームメイン処理 if ( FAILED( UpdateFrame() ) ) break; Sleep(1); } else { WaitMessage(); } } // DirectX8オブジェクトの削除 ReleaseD3D(); return msg.wParam; } //------------------------------------------------------------------------------------------------- // ウィンドウプロシジャ関数(WindowProcedure) // メッセージ処理を行う //------------------------------------------------------------------------------------------------- LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch ( message ) { case WM_SIZE: if ( wParam == SIZE_MAXHIDE || wParam == SIZE_MINIMIZED ) g_appActive = FALSE; else g_appActive = TRUE; ResetWindow(); break; case WM_MOVE: ResetWindow(); break; case WM_KEYDOWN: // キーを押したとき switch ( wParam ) { case VK_ESCAPE: PostMessage(hWnd, WM_CLOSE, 0, 0); break; } break; case WM_SETCURSOR: // カーソルの設定 SetCursor(NULL); break; case WM_DESTROY: // 閉じるボタンをクリックした時 PostQuitMessage(0); // WM_QUITメッセージを発行 break; default: // 上記以外のメッセージはWindowsへ処理を任せる return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } //------------------------------------------------------------------------------------------------- // 関数名 :InitApp // 機能概要:表示するウィンドウの定義、登録、表示 // 戻り値 :正常終了のとき1、以上終了のとき0 //------------------------------------------------------------------------------------------------- BOOL InitApp(HINSTANCE hThisInst, int nWinMode) { WNDCLASSEX wc; //ウィンドウクラス構造体 // ウィンドウクラスを定義する wc.cbSize = sizeof(WNDCLASSEX); // WNDCLASSEX構造体のサイズを設定 wc.style = NULL; // ウィンドウスタイル(デフォルト) wc.lpfnWndProc = WinProc; // ウィンドウ関数 wc.cbClsExtra = 0; // 通常は使わない(0にしておく) wc.cbWndExtra = 0; // 通常は使わない(0にしておく) wc.hInstance = hThisInst; // このインスタンスへのハンドル wc.hIcon = NULL; // ラージアイコン(なし) wc.hCursor = LoadCursor(NULL, IDC_ARROW); // カーソルスタイル wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // ウィンドウの背景(黒) wc.lpszMenuName = NULL; // メニュー(なし) wc.lpszClassName = szWinName; // ウィンドウクラス名 wc.hIconSm = NULL; // スモールアイコン(なし) // ウィンドウクラスの登録 if (!RegisterClassEx(&wc)) return (FALSE); // ウィンドウクラスの登録ができたので、ウィンドウを生成する if ( WINMODE ) { /* ウィンドウ・モード用のウィンドウを生成 */ hWnd = CreateWindow( szWinName, // ウィンドウクラスの名前 szWinTitle, // ウィンドウタイトル WS_OVERLAPPEDWINDOW, // ウィンドウスタイル 0, // ウィンドウの左角X座標 0, // ウィンドウの左角Y座標 CW_USEDEFAULT, // ウィンドウの幅 CW_USEDEFAULT, // ウィンドウの高さ NULL, // 親ウィンドウ(なし) NULL, // メニュー(なし) hThisInst, // このプログラムのインスタンスのハンドル NULL // 追加引数(なし) ); 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); } else { /* フルスクリーン・モード用のウィンドウを生成 */ hWnd = CreateWindow( szWinName, // ウィンドウクラスの名前 szWinTitle, // ウィンドウタイトル WS_VISIBLE | WS_POPUP, // ウィンドウスタイル 0, // ウィンドウの左角X座標 0, // ウィンドウの左角Y座標 SCREEN_WIDTH, // ウィンドウの幅 SCREEN_HEIGHT, // ウィンドウの高さ NULL, // 親ウィンドウ(なし) NULL, // メニュー(なし) hThisInst, // このプログラムのインスタンスのハンドル NULL // 追加引数(なし) ); } ShowWindow(hWnd, nWinMode); // ウィンドウを表示 ValidateRect(hWnd, 0); // WM_PAINTが呼ばれないようにする UpdateWindow(hWnd); // ウィンドウの更新 return (TRUE); // InitApp関数の正常終了 } //----------------------------------------------------------------------------- // 関数名 : InitDX8()  // 機能概要: Direct Draw オブジェクトの生成 // 戻り値 : 正常終了のとき:DD_OK、異常終了のとき:エラーコード //----------------------------------------------------------------------------- HRESULT InitDX8(void) { D3DDISPLAYMODE DispMode; // ディスプレイモード HRESULT hr; /* DirectX8オブジェクトの生成 */ gl_lpD3d = Direct3DCreate8(D3D_SDK_VERSION); if( !gl_lpD3d ) { // オブジェクト生成失敗 MessageBox(hWnd, "DirectXD3D8オブジェクト生成失敗", "ERROR", MB_OK); return E_FAIL; } /* DirectX8のプレゼンテーションパラメータを設定 */ // ディスプレイデータ格納構造体初期化 ZeroMemory(&gl_d3dpp, sizeof(D3DPRESENT_PARAMETERS)); // 現在のディスプレイモードデータ取得 gl_lpD3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DispMode); // バックバッファフォーマットをディスプレイと等価に gl_d3dpp.BackBufferFormat = DispMode.Format; // 横ドット幅設定 gl_d3dpp.BackBufferWidth = SCREEN_WIDTH; // 縦ドット幅設定 gl_d3dpp.BackBufferHeight = SCREEN_HEIGHT; // バックバッファの数 gl_d3dpp.BackBufferCount = 1; // フリップの方法(通常はこの定数でよい) gl_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // gl_d3dpp.EnableAutoDepthStencil = TRUE; // ステンシルフォーマット gl_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // ウインドウモードの設定 gl_d3dpp.Windowed = WINMODE; /* デバイスオブジェクトの生成 */ //高性能なハードウェアデバイスの生成を試みる hr = gl_lpD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &gl_d3dpp, &gl_lpD3ddev); if ( FAILED(hr) ) { //ハードウェアデバイスの生成を試みる hr = gl_lpD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &gl_d3dpp, &gl_lpD3ddev); if ( FAILED(hr) ) { //ソフトウェアデバイスの生成を試みる hr = gl_lpD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &gl_d3dpp, &gl_lpD3ddev); if ( FAILED(hr) ) { //--どのデバイスも取得できなかった MessageBox(hWnd, "DirectXデバイス生成失敗", "ERROR", MB_OK); return E_FAIL; } } } return S_OK; } //----------------------------------------------------------------------------- // 関数名 : InitRender() // 機能概要: 描画の設定など //----------------------------------------------------------------------------- void InitRender(void) { // テクスチャの設定 gl_lpD3ddev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); gl_lpD3ddev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); gl_lpD3ddev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); // アルファ・ブレンディングを行う gl_lpD3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // 透過処理を行う gl_lpD3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // 半透明処理を行う gl_lpD3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); } //----------------------------------------------------------------------------- // 関数名 : ReleaseD3D() // 機能概要: DirectX8オブジェクトの開放 //----------------------------------------------------------------------------- void ReleaseD3D(void) { // テクスチャの開放 if ( gl_Texture1 != NULL ) { gl_Texture1->Release(); gl_Texture1 = NULL; } if ( gl_Texture2 != NULL ) { gl_Texture2->Release(); gl_Texture2 = NULL; } //デバイスオブジェクトの開放 if ( gl_lpD3ddev != NULL ) { gl_lpD3ddev->Release(); gl_lpD3ddev = NULL; } //DirectX8オブジェクトの開放 if ( gl_lpD3d != NULL ) { gl_lpD3d->Release(); gl_lpD3d = NULL; } } //----------------------------------------------------------------------------- // 関数名 : ResetWindow() // 機能概要: ウィンドウの再設定 //----------------------------------------------------------------------------- void ResetWindow(void) { if ( gl_lpD3ddev ) { // ディスプレイ・パラメータの値を使ってウィンドウをリセットする gl_lpD3ddev->Reset(&gl_d3dpp); // 描画の設定 InitRender(); } } //----------------------------------------------------------------------------- // 関数名 : UpdateFrame() // 機能概要: ゲームメイン処理 //----------------------------------------------------------------------------- BOOL UpdateFrame(void) { /* 現在のキー情報を取得 */ if ( !GetKeyboardState(gl_KeyTbl) ) { MessageBox(hWnd, "キー情報の取得に失敗", "ERROR", MB_OK); return (FALSE); } /* 画面のクリア */ gl_lpD3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255), 0.0, 0); /* シーン開始 */ gl_lpD3ddev->BeginScene(); /* 頂点フォーマットを設定 */ gl_lpD3ddev->SetVertexShader(FVF_TLVERTEX); /* 処理の振り分け */ switch ( g_FrameNo ) { case START_INIT: // スタート画面を表示する前に実行する初期化関数を実行 StartInit(); case START_FRAME: // スタート画面表示処理関数を実行 StartFrame(); break; case GAME_INIT: // ゲーム画面を表示する前に実行する初期化関数を実行 case GAME_FRAME: // ゲーム画面表示処理関数を実行 break; default: MessageBox(hWnd, "g_FrameNoの値が例外です。", "ERROR", MB_OK); return (FALSE); } /* シーン終了 */ gl_lpD3ddev->EndScene(); /* フリップ */ gl_lpD3ddev->Present(NULL, NULL, NULL, NULL); return (TRUE); } //----------------------------------------------------------------------------- // 関数名 : StartInit() // 機能概要: スタート画面初期化処理 //----------------------------------------------------------------------------- void StartInit(void) { //--------------------------------------------------- 各変数の初期化 // スタート画面で使用するテクスチャの作成 CreateStartTexture(); // 頂点データを格納する InitVertex(VertexDataTbl1, 100.0, 100.0, 164.0, 164.0, 255); InitVertex(VertexDataTbl2, 400.0, 300.0, 496.0, 396.0, 255); //--------------------------------------------------- フレームナンバーセット g_FrameNo = START_FRAME; } //----------------------------------------------------------------------------- // 関数名 : StartFrame() // 機能概要: スタート画面処理 //----------------------------------------------------------------------------- void StartFrame(void) { /* 描画処理 */ // キャラクタ1を描画 gl_lpD3ddev->SetTexture(0, gl_Texture1); gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, VertexDataTbl1, sizeof(TLVERTX)); // キャラクタ2を描画 gl_lpD3ddev->SetTexture(0, gl_Texture2); gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, VertexDataTbl2, sizeof(TLVERTX)); // リターンキーが押されたら、ゲーム開始 if ( gl_KeyTbl[VK_RETURN] & 0x80 ) g_FrameNo = GAME_INIT; } //---------------------------------------------------------------------------------------- // 関数名 : InitVertex()  // 機能概要: 頂点データを格納する //---------------------------------------------------------------------------------------- void InitVertex(LPTLVERTEX v, float x1, float y1, float x2, float y2, int Alpha) { D3DCOLOR color; // 頂点カラー // 半透明処理をするかどうかを判断し、頂点カラーを決定 if ( Alpha == 255 ) color = D3DCOLOR_XRGB(255,255,255); else color = D3DCOLOR_RGBA(255,255,255,Alpha); //頂点配列をゼロクリア ZeroMemory(v, sizeof(TLVERTX)); //---頂点A1のデータ定義 v[0].x = x1; // 頂点X座標 v[0].y = y1; // 頂点Y座標 v[0].z = 0.0f; // 頂点Z座標 v[0].rhw = 1.0f; // 2Dを扱うときの値 v[0].tu = 0.0f; // テクスチャのX座標 v[0].tv = 0.0f; // テクスチャのY座標 v[0].color = color; // 頂点色 //---頂点A2のデータ定義 v[1].x = x2; v[1].y = y1; v[1].z = 0.0f; v[1].rhw = 1.0f; v[1].tu = 1.0f; v[1].tv = 0.0f; v[1].color = color; //---頂点A3のデータ定義 v[2].x = x2; v[2].y = y2; v[2].z = 0.0f; v[2].rhw = 1.0f; v[2].tu = 1.0f; v[2].tv = 1.0f; v[2].color = color; //---頂点A4のデータ定義 v[3].x = x1; v[3].y = y2; v[3].z = 0.0f; v[3].rhw = 1.0f; v[3].tu = 0.0f; v[3].tv = 1.0f; v[3].color = color; } //----------------------------------------------------------------------------- // 関数名 : CreateStartTexture() // 機能概要: スタート画面用テクスチャの作成・再生成 //----------------------------------------------------------------------------- void CreateStartTexture(void) { HRESULT hr; char buff[80]; // キャラクタ1 hr = D3DXCreateTextureFromFile(gl_lpD3ddev, gl_szCharFileName1, &gl_Texture1); if ( FAILED(hr) ) { wsprintf(buff, "%s をテクスチャ1として読み込めませんでした", gl_szCharFileName1); MessageBox(hWnd, buff, "ERROR", MB_OK); return; } // キャラクタ2 hr = D3DXCreateTextureFromFile(gl_lpD3ddev, gl_szCharFileName2, &gl_Texture2); if ( FAILED(hr) ) { wsprintf(buff, "%s をテクスチャ2として読み込めませんでした", gl_szCharFileName2); MessageBox(hWnd, buff, "ERROR", MB_OK); return; } }