学了绘制简单的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;
}