學了繪制簡單的2D圖形以及3D物體之後,該學學怎麼控制物體了!
之前一直是用的是Windows自帶的消息循環,WM_KEYDOWN,WM_MOUSELBUTTONDOWN等等,但是這個慢的不行,完全跟不上遊戲的速度。以前用GDI/GDI+寫遊戲的時候使用過一個GetAsyncKeyState方法,可以用于實時的檢測鍵盤按下,雖然簡單,不過據本人親測,會被360發現...是以還是好好學學正統的遊戲控制吧...傳說中的DIrectInput!
準備工作:
使用DirectInput時,需要包含DInput.h頭檔案,然後還要引入dinput8.lib以及dxguid.lib庫檔案。
#include "DInput.h"
//添加庫檔案
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
建立接口以及裝置:
<span style="white-space:pre"> </span>IDirectInput8* m_pDirectInput; //DirectInput接口對象
<span style="white-space:pre"> </span>//初始化接口對象
DirectInput8Create(
hInstance, //程式執行個體的句柄
DIRECTINPUT_VERSION, //0x0800目前使用的DirectInput版本号
IID_IDirectInput8, //接口辨別,使用IID_IDirectInput8即可
(void**)&m_pDirectInput, //建立的接口的對象的指針
NULL //COM對象相關聯參數,為NULL
);
鍵盤和滑鼠有設定的GUID值(全局唯一ID),其他裝置需要通過EnumDevices方法獲得GUID值。
初始化滑鼠以及鍵盤裝置:
<span style="white-space:pre"> </span>IDirectInputDevice8* m_KeyboardDevice; //鍵盤裝置接口
char m_keyBuffer[256]; //用于儲存鍵盤鍵值的數組
IDirectInputDevice8* m_MouseDevice; //滑鼠裝置接口
DIMOUSESTATE m_MouseState; //滑鼠鍵值存儲結構體
<span style="white-space:pre"> </span>//初始化鍵盤裝置
m_pDirectInput->CreateDevice( //建立裝置
GUID_SysKeyboard, //GUID值,對于滑鼠和鍵盤有宏定義,其餘裝置需要通過枚舉找出
&m_KeyboardDevice, //鍵盤裝置指針的指針
NULL //COM相關參數,為NULL
);
m_KeyboardDevice->SetCooperativeLevel(//設定協作級别
hWnd, //視窗句柄
keyboardCoopFlags //協作級别(前台背景,獨占非獨占)
);
m_KeyboardDevice->SetDataFormat( //設定資料格式
&c_dfDIKeyboard); //鍵盤滑鼠等的資料格式,宏定義
m_KeyboardDevice->Acquire(); //獲得裝置控制權
m_KeyboardDevice->Poll(); //輪詢裝置
//初始化滑鼠裝置
m_pDirectInput->CreateDevice(GUID_SysMouse, &m_MouseDevice, NULL);
m_MouseDevice->SetCooperativeLevel(hWnd, mouseCoopFlags);
m_MouseDevice->SetDataFormat(&c_dfDIMouse);
m_MouseDevice->Acquire();
m_MouseDevice->Poll();
建立之後,需要設定協作級别,通過SetCooperativeLevel協作級别分為前台,背景以及共享,獨占模式。具體的參數查閱MSDN。
然後要設定資料格式,通過SetDataFormat設定資料格式。
獲得裝置輸入消息以及讀取:
<span style="white-space:pre"> </span>//獲得鍵盤輸入消息
HRESULT hr = m_KeyboardDevice->GetDeviceState(sizeof(m_keyBuffer), (void**)&m_keyBuffer);
if (hr)
{
m_KeyboardDevice->Acquire();
m_KeyboardDevice->GetDeviceState(sizeof(m_keyBuffer), (void**)&m_keyBuffer);
}
//獲得滑鼠輸入資訊
hr = m_MouseDevice->GetDeviceState(sizeof(m_MouseState), (void**)&m_MouseState);
if (hr)
{
m_MouseDevice->Acquire();
m_MouseDevice->GetDeviceState(sizeof(m_MouseState), (void**)&m_MouseState);
}
對于按鍵讀取,我們之前定義了一個數組,判斷哪一個鍵被按下了,隻需要根據鍵碼對應的索引值讀取數組中的值再&0x80即可:
if (m_keyBuffer[DIK_A] & 0x80)//判斷A鍵是否被按下
return true;
return false;
滑鼠的資訊為一個結構體,有1X,1Y,1Z,以及rgbButton,分别表示X坐标,Y坐标,滾輪,按鍵資訊。按鍵資訊類似鍵盤,按照索引值對應不同按鍵。0為左鍵,1為右鍵:
return (m_MouseState.rgbButtons[iButton] & 0x80) != 0;//判斷左鍵是否被按下
return (float) m_MouseState.lX;//傳回滑鼠X坐标
釋放資源:
//釋放對象
if (m_KeyboardDevice)
m_KeyboardDevice->Unacquire();
if (m_MouseDevice)
m_MouseDevice->Unacquire();
SAFE_RELEASE(m_MouseDevice);
SAFE_RELEASE(m_KeyboardDevice);
SAFE_RELEASE(m_pDirectInput);
SAFE_RELEASE定義如下:
#define SAFE_RELEASE(p) {if(p) {(p)->Release(); (p) = NULL;}}
下面是按照淺墨大神的例子,封裝的一個DirectInput的類:
頭檔案:
#ifndef __CDIRECTINPUT_H_
#define __CDIRECTINPUT_H_
#include "DInput.h"
//添加庫檔案
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#pragma once
class CDirectInput
{
private:
IDirectInput8* m_pDirectInput; //DirectInput接口對象
IDirectInputDevice8* m_KeyboardDevice; //鍵盤裝置接口
char m_keyBuffer[256]; //用于儲存鍵盤鍵值的數組
IDirectInputDevice8* m_MouseDevice; //滑鼠裝置接口
DIMOUSESTATE m_MouseState; //滑鼠鍵值存儲結構體
public:
CDirectInput(void);
virtual ~CDirectInput(void);
//初始化DirectInput以及鍵盤滑鼠裝置
HRESULT Init(HWND hWnd, HINSTANCE hInstance, DWORD keyboardCoopFlags, DWORD mouseCoopFlags);
//獲得輸入資訊
void GetInput();
//檢測鍵盤某按鍵是否被按下
bool IsKeyDown(int iKey);
//檢測滑鼠某按鍵是否被按下
bool IsMouseButtonDown(int iButton);
//獲得滑鼠X軸坐标值
float MouseDX();
//獲得滑鼠Y軸坐标值
float MouseDY();
//獲得滑鼠Z軸(滑鼠滾輪)坐标值
float MouseDZ();
};
#endif
CPP檔案:
#include "stdafx.h"
#include "DirectInput.h"
CDirectInput::CDirectInput(void)
{
//賦初值
m_pDirectInput = NULL;
m_KeyboardDevice = NULL;
m_MouseDevice = NULL;
ZeroMemory(m_keyBuffer, sizeof(m_keyBuffer));
ZeroMemory(&m_MouseState, sizeof(m_MouseState));
}
CDirectInput::~CDirectInput(void)
{
//釋放對象
if (m_KeyboardDevice)
m_KeyboardDevice->Unacquire();
if (m_MouseDevice)
m_MouseDevice->Unacquire();
SAFE_RELEASE(m_MouseDevice);
SAFE_RELEASE(m_KeyboardDevice);
SAFE_RELEASE(m_pDirectInput);
}
HRESULT CDirectInput::Init(HWND hWnd, HINSTANCE hInstance, DWORD keyboardCoopFlags, DWORD mouseCoopFlags)
{
//初始化接口對象
DirectInput8Create(
hInstance, //程式執行個體的句柄
DIRECTINPUT_VERSION, //0x0800目前使用的DirectInput版本号
IID_IDirectInput8, //接口辨別,使用IID_IDirectInput8即可
(void**)&m_pDirectInput, //建立的接口的對象的指針
NULL //COM對象相關聯參數,為NULL
);
//初始化鍵盤裝置
m_pDirectInput->CreateDevice( //建立裝置
GUID_SysKeyboard, //GUID值,對于滑鼠和鍵盤有宏定義,其餘裝置需要通過枚舉找出
&m_KeyboardDevice, //鍵盤裝置指針的指針
NULL //COM相關參數,為NULL
);
m_KeyboardDevice->SetCooperativeLevel(//設定協作級别
hWnd, //視窗句柄
keyboardCoopFlags //協作級别(前台背景,獨占非獨占)
);
m_KeyboardDevice->SetDataFormat( //設定資料格式
&c_dfDIKeyboard); //鍵盤滑鼠等的資料格式,宏定義
m_KeyboardDevice->Acquire(); //獲得裝置控制權
m_KeyboardDevice->Poll(); //輪詢裝置
//初始化滑鼠裝置
m_pDirectInput->CreateDevice(GUID_SysMouse, &m_MouseDevice, NULL);
m_MouseDevice->SetCooperativeLevel(hWnd, mouseCoopFlags);
m_MouseDevice->SetDataFormat(&c_dfDIMouse);
m_MouseDevice->Acquire();
m_MouseDevice->Poll();
return true;
}
void CDirectInput::GetInput()
{
//獲得鍵盤輸入消息
HRESULT hr = m_KeyboardDevice->GetDeviceState(sizeof(m_keyBuffer), (void**)&m_keyBuffer);
if (hr)
{
m_KeyboardDevice->Acquire();
m_KeyboardDevice->GetDeviceState(sizeof(m_keyBuffer), (void**)&m_keyBuffer);
}
//獲得滑鼠輸入資訊
hr = m_MouseDevice->GetDeviceState(sizeof(m_MouseState), (void**)&m_MouseState);
if (hr)
{
m_MouseDevice->Acquire();
m_MouseDevice->GetDeviceState(sizeof(m_MouseState), (void**)&m_MouseState);
}
}
bool CDirectInput::IsKeyDown(int iKey)
{
if (m_keyBuffer[iKey] & 0x80)
return true;
return false;
}
bool CDirectInput::IsMouseButtonDown(int iButton)
{
return (m_MouseState.rgbButtons[iButton] & 0x80) != 0;
}
float CDirectInput::MouseDX()
{
return (float) m_MouseState.lX;
}
float CDirectInput::MouseDY()
{
return (float) m_MouseState.lY;
}
float CDirectInput::MouseDZ()
{
return (float) m_MouseState.lZ;
}
這裡我畫了個茶壺,然後通過上面封裝的CDirectInput類來“調戲”這個茶壺...
主要使用部分,關于DirectInput類的東東,我都放在了OnLogic函數裡面,是跟Render同級别的被調用的函數:
void onLogic(float fElapsedTime)
{
g_pDirectInput->GetInput();
if (g_pDirectInput->IsKeyDown(DIK_1))
g_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
else if (g_pDirectInput->IsKeyDown(DIK_2))
g_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
//使用CDirectInput類:
static float fposX = 0.0f, fposY = 0.0f, fposZ = 0.0f;
//左鍵按下,拖動
if (g_pDirectInput->IsMouseButtonDown(0))
{
fposX += g_pDirectInput->MouseDX() * 0.0008f;
fposY -= g_pDirectInput->MouseDY() * 0.0008f;
}
//滾輪
fposZ += g_pDirectInput->MouseDZ() * 0.02f;
//按鍵移動
if (g_pDirectInput->IsKeyDown(DIK_A))
fposX -= 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_D))
fposX += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_W))
fposY += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_S))
fposY -= 0.08f;
D3DXMatrixTranslation(&g_matWorld, fposX, fposY, fposZ);
static float angle_x = 0.0f;
static float angle_y = 0.0f;
if (g_pDirectInput->IsKeyDown(DIK_UP))
angle_x += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_DOWN))
angle_x -= 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_LEFT))
angle_y += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_RIGHT))
angle_y -= 0.08f;
//旋轉操作
D3DXMatrixRotationX(&g_matRX, angle_x);
D3DXMatrixRotationY(&g_matRY, angle_y);
g_matWorld = g_matWorld * g_matRX * g_matRY;
g_pDevice->SetTransform(D3DTS_WORLD,&g_matWorld);
}
運作一下:
平移操作:
旋轉操作:
完整的Demo(不包括CDirectInput類):
// D3DDemo.cpp : 定義應用程式的入口點。
//
#include "stdafx.h"
#include "D3DDemo.h"
#include "DirectInput.h"
#define MAX_LOADSTRING 100
// 全局變量:
HINSTANCE hInst; // 目前執行個體
TCHAR szTitle[MAX_LOADSTRING]; // 标題欄文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主視窗類名
// 此代碼子產品中包含的函數的前向聲明:
HWND g_hWnd;
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//---------改造3D視窗需要的内容------------
LPDIRECT3D9 g_pD3D = NULL; //D3D接口指針
LPDIRECT3DDEVICE9 g_pDevice = NULL;//D3D裝置指針
//立方體的接口
LPD3DXMESH g_pteapot = NULL;
LPD3DXMESH g_pbox = NULL;
//控制類
CDirectInput* g_pDirectInput = NULL;
void onCreatD3D()
{
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!g_pD3D)
return;
//檢測硬體裝置能力的方法
/*D3DCAPS9 caps;
ZeroMemory(&caps, sizeof(caps));
g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);*/
//獲得相關資訊,螢幕大小,像素點屬性
D3DDISPLAYMODE d3ddm;
ZeroMemory(&d3ddm, sizeof(d3ddm));
g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
//設定全屏或視窗模式
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
/*d3dpp.Windowed = false;
d3dpp.BackBufferWidth = d3ddm.Width;
d3dpp.BackBufferHeight = d3ddm.Height;*/
d3dpp.Windowed = true;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.BackBufferCount = 1;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//交換後原緩沖區資料丢棄
//是否開啟自動深度模闆緩沖
d3dpp.EnableAutoDepthStencil = true;
//目前自動深度模闆緩沖的格式
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;//每個像素點有16位的存儲空間,存儲離錄影機的距離
g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pDevice);
if (!g_pDevice)
return;
//設定渲染狀态,設定啟用深度值
g_pDevice->SetRenderState(D3DRS_ZENABLE, true);
//設定渲染狀态,關閉燈光
//g_pDevice->SetRenderState(D3DRS_LIGHTING, false);
//頂點法線
g_pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
//開啟鏡面反射
g_pDevice->SetRenderState(D3DRS_SPECULARENABLE, true);
//設定渲染狀态,裁剪模式
g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}
void Transform()
{
//ViewTransform:取景變換
D3DXVECTOR3 vEyePt(0.0f, 0.0f, -10.0f); //錄影機世界坐标
D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f); //觀察點世界坐标
D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f); //錄影機的上向量,通常為(0.0f, 1.0f, 0.0f)
D3DXMATRIXA16 matView; //View變換的矩陣
//根據上面的結果計算出矩陣,存入矩陣中
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
//進行取景變換
g_pDevice->SetTransform(D3DTS_VIEW, &matView);
//ProjectionTransform:投影變換
D3DXMATRIXA16 matProj; //投影變換矩陣
//生成投影變換矩陣,存入上面的矩陣中
D3DXMatrixPerspectiveFovLH(
&matProj, //輸出結果矩陣
D3DX_PI / 4, //視域角度,一般為PI/4
1.0f, //顯示屏的長寬比
1.0f, //視截體中近截面距離錄影機的位置
100.0f //視截體中遠截面距離錄影機的位置
);
//進行投影變換
g_pDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}
//設定光照
enum Light
{
Point, //點光源
Directional, //平行光
Spot //聚光燈
};
void SetLight(Light l)
{
//三種光源類型
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(light));
switch (l)
{
//點光源
case Point:
light.Type = D3DLIGHT_POINT; //光源類型
light.Ambient = D3DXCOLOR(0.6f, 0.6f, 0.6f, 1.0f); //光源的環境光顔色值
light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); //光源的漫反射光顔色值
light.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f); //光源的鏡面反射光顔色值
light.Position = D3DXVECTOR3(0.0f,20.0f, 0.0f); //光源的位置
light.Attenuation0 = 1.0f; //衰減系數0
light.Attenuation1 = 0.0f; //衰減系數1
light.Attenuation2 = 0.0f; //衰減系數2
light.Range = 300.0f; //光源的光照範圍
break;
case Directional:
//平行光源
light.Type = D3DLIGHT_DIRECTIONAL; //光源類型
light.Ambient = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); //光源的環境光顔色值
light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); //光源的漫反射光顔色值
light.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f); //光源的鏡面反射光顔色值
light.Position = D3DXVECTOR3(0.0f,20.0f, 0.0f); //光源的位置
break;
case Spot:
//聚光燈光源
light.Type = D3DLIGHT_SPOT; //光源類型
light.Ambient = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f); //光源的環境光顔色值
light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); //光源的漫反射光顔色值
light.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f); //光源的鏡面反射光顔色值
light.Position = D3DXVECTOR3(100.0f,100.0f, 100.0f); //光源的位置
light.Direction = D3DXVECTOR3(-1.0f, -1.0f, -1.0f); //光源方向
light.Attenuation0 = 1.0f; //衰減系數0
light.Attenuation1 = 0.0f; //衰減系數1
light.Attenuation2 = 0.0f; //衰減系數2
light.Range = 300.0f; //光源的光照範圍
light.Falloff = 0.1f; //聚光燈特有的參數
light.Phi = D3DX_PI / 3.0f; //聚光燈特有的參數
light.Theta = D3DX_PI / 6.0f; //聚光燈特有的參數
break;
default:
break;
}
//設定光照
g_pDevice->SetLight(0, &light);
//啟用光照
g_pDevice->LightEnable(0, true);
//設定一下環境光
g_pDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(200, 200, 200));
}
//設定材質
void SetMaterial()
{
D3DMATERIAL9 mtrl;
ZeroMemory(&mtrl, sizeof(mtrl));
mtrl.Ambient = D3DXCOLOR(1.0f, 0.5f, 0.1f, 1.0f); //物體表面對環境光的反射率,為一個顔色值
mtrl.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); //物體表面對漫反射光的反射率,為一個顔色值
mtrl.Specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); //物體表面對鏡面反射光的反射率,為一個顔色值
mtrl.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f); //物體自發光的顔色值
//mtrl.Power 鏡面反射指數,該值越大,高光強度和周圍亮度相差就越大
g_pDevice->SetMaterial(&mtrl);
}
void onInit()
{
//初始化D3D
onCreatD3D();
//初始化對象
//生成茶壺
D3DXCreateTeapot(
g_pDevice, //裝置對象
&g_pteapot, //建立的對象的指針
NULL //通常為NULL
);
//生成立方體
D3DXCreateBox(
g_pDevice, //裝置對象
1.0f, 1.0f, 1.0f, //X,Y,Z方向的長度
&g_pbox, //建立的對象的指針
NULL //存儲繪制網格的三角形索引參數,不使用,置為NULL
);
SetMaterial();
SetLight(Light::Point);
}
void onDestroy()
{
if (!g_pDevice)
g_pDevice->Release();
g_pDevice = NULL;
}
D3DXMATRIXA16 g_matWorld;
D3DXMATRIXA16 g_matRY, g_matRX;
void onLogic(float fElapsedTime)
{
g_pDirectInput->GetInput();
if (g_pDirectInput->IsKeyDown(DIK_1))
g_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
else if (g_pDirectInput->IsKeyDown(DIK_2))
g_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
//使用CDirectInput類:
static float fposX = 0.0f, fposY = 0.0f, fposZ = 0.0f;
//左鍵按下,拖動
if (g_pDirectInput->IsMouseButtonDown(0))
{
fposX += g_pDirectInput->MouseDX() * 0.0008f;
fposY -= g_pDirectInput->MouseDY() * 0.0008f;
}
//滾輪
fposZ += g_pDirectInput->MouseDZ() * 0.02f;
//按鍵移動
if (g_pDirectInput->IsKeyDown(DIK_A))
fposX -= 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_D))
fposX += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_W))
fposY += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_S))
fposY -= 0.08f;
D3DXMatrixTranslation(&g_matWorld, fposX, fposY, fposZ);
static float angle_x = 0.0f;
static float angle_y = 0.0f;
if (g_pDirectInput->IsKeyDown(DIK_UP))
angle_x += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_DOWN))
angle_x -= 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_LEFT))
angle_y += 0.08f;
if (g_pDirectInput->IsKeyDown(DIK_RIGHT))
angle_y -= 0.08f;
//旋轉操作
D3DXMatrixRotationX(&g_matRX, angle_x);
D3DXMatrixRotationY(&g_matRY, angle_y);
g_matWorld = g_matWorld * g_matRX * g_matRY;
g_pDevice->SetTransform(D3DTS_WORLD,&g_matWorld);
}
void onRender(float fElasedTime)
{
//前兩個參數是0和NULL時,清空整個遊戲視窗的内容(清的是背景)
//第三個是清除的對象:前面表示清除顔色緩沖區,後面表示清除深度緩沖區,D3DCLEAR_STENCIL清空模闆緩沖區
g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,100,100), 1.0f, 0);
g_pDevice->BeginScene();
Transform();
//繪制茶壺
D3DXMATRIXA16 matTeapot;
g_pteapot->DrawSubset(0);
//繪制立方體
D3DXMATRIXA16 matBox;
//g_pbox->DrawSubset(0);
g_pDevice->EndScene();
g_pDevice->Present(NULL, NULL, NULL, NULL);
}
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代碼。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字元串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_D3DDEMO, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 執行應用程式初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_D3DDEMO));
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
static DWORD dwTime = timeGetTime();
DWORD dwCurrentTime = timeGetTime();
DWORD dwElapsedTime = dwCurrentTime - dwTime;
float fElapsedTime = dwElapsedTime * 0.001f;
//------------渲染和邏輯部分代碼----------
onLogic(fElapsedTime);
onRender(fElapsedTime);
//-----------------------------------------
if (dwElapsedTime < 1000 / 60)
{
Sleep(1000/ 60 - dwElapsedTime);
}
dwTime = dwCurrentTime;
}
}
onDestroy();
return (int) msg.wParam;
}
//
// 函數: MyRegisterClass()
//
// 目的: 注冊視窗類。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_D3DDEMO));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_D3DDEMO);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 函數: InitInstance(HINSTANCE, int)
//
// 目的: 儲存執行個體句柄并建立主視窗
//
// 注釋:
//
// 在此函數中,我們在全局變量中儲存執行個體句柄并
// 建立和顯示主程式視窗。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将執行個體句柄存儲在全局變量中
g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!g_hWnd)
{
return FALSE;
}
SetMenu(g_hWnd, NULL);
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);
onInit();
//初始化DirectInput
g_pDirectInput = new CDirectInput();
g_pDirectInput->Init(g_hWnd, hInstance, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
return TRUE;
}
//
// 函數: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 處理主視窗的消息。
//
// WM_COMMAND - 處理應用程式菜單
// WM_PAINT - 繪制主視窗
// WM_DESTROY - 發送退出消息并傳回
//
//
LRESULT CALLBACK WndProc(HWND g_hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
DestroyWindow(g_hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(g_hWnd, message, wParam, lParam);
}
return 0;
}