学了绘制简单的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 );
初始化鼠标以及键盘设备:
<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;}}
头文件:
#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
#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; }