OpenGL系统设计-DirectInput(2)

我们把对DirectInput进行初始化的过程放在DXInit函数中。

 

#include <dinput.h>             //DirectInput头文件

LPDIRECTINPUT8          g_DI;   //DirectInput对象指针

LPDIRECTINPUTDEVICE8    g_KDIDev;   //DirectInput设备对象指针

 

int DXInit()

{

    //先创建DirectInput对象

    if ( DirectInput8Create(hInst,          // 应用程序实例句柄,

// 这里的hInst是全局变量

        DIRECTINPUT_VERSION,        // Direct Input版本

        IID_IDirectInput8,      // 版本为8

        (void**)&g_DI,          // Direct Input对象

        NULL ) )            // 指向IUnknown接口的指针,通常取NULL

    {

        return FALSE;                       // 初始化失败就返回FALSE

    }

   

    // 创建键盘设备

    if ( g_DI->CreateDevice(GUID_SysKeyboard, &g_KDIDev, NULL ) )

    {

        return FALSE;                       // 创建失败就返回FALSE

    }

   

    // 设置键盘设备的数据格式

    if ( g_KDIDev->SetDataFormat(&c_dfDIKeyboard) )

    {

        return FALSE;                       // 设置失败返回FALSE

    }

   

 

DirectInput还需要设置设备的工作协作等级,其中DISCL_BACKGROUNDDISCL_FOREGROUND必须选择一种,分别表示后台和前台数据接收。当选择前者时,表示即便应用程序非当前活动程序,DirectInupt仍然会接收输入数据,并且根据程序的设计来进入不同的流程。后者则表示只有程序是当前活动程序,DirectInput才会接收输入数据,并且一旦应用程序切换到后台,就会自动失去设备。

DISCL_NONEXCLUSIVEDISCL_EXCLUSIVE也必须选择一种,前者表示对输入设备的使用的非独占式使用,不会影响到其他应用程序对该设备的使用。后者表示对输入设备独占使用,当程序获得设备时,其他程序就不能使用该设备,哪怕是非独占式使用都不行

 

if ( g_KDIDev->SetCooperativeLevel(g_hWnd, DISCL_FOREGROUND |

                                DISCL_NONEXCLUSIVE) )

    {

        return FALSE;                       // 设置失败返回FALSE

    }

   

    if (g_KDIDev)

        g_KDIDev->Acquire();                // 创建设备成功后需要获得设备,

//否则无法接收输入数据

    else

        return FALSE;  

   

    return TRUE;                            // 初始化成功,返回TRUE

}

 

DirectInput初始化相反的过程就是关闭DirectInput,和OpenGL一样,我们也放在一个DXShutdown函数中处理。

 

void DXShutdown()

{

    if (g_DI)

    {

        if (g_KDIDev)

        {

            g_KDIDev->Unacquire();

            g_KDIDev->Release();

            g_KDIDev = NULL;

        }

       

        g_DI->Release();

        g_DI = NULL;

    }

}

 

因为我们设置的DirectInput的协作等级为前台非独占式工作模式,因此当应用程序切换到后台后,会自动失去设备。为了使得程序重新切换回前台时,设备继续正常工作,我们必须手动的获取它,应用程序是不会自动获取设备的。对设备的重新获取,放在Wndproc回调函数中。

 

LRESULT CALLBACK WndProc(HWND   hWnd,

                         UINT   uMsg,  

                         WPARAM wParam,

                         LPARAM lParam)

{

    switch (uMsg)                              

    {

    case WM_ACTIVATE:                   //程序处于活动状态

        {

            if (!HIWORD(wParam))   

            {

                active=TRUE;       

            }

            else

            {

                active=FALSE;

            }

 

            // 如果键盘设备为空,就直接返回

            if (NULL == g_KDIDev)

                return S_FALSE;

 

            if (active)

            {

                // 获得输入设备

                g_KDIDev->Acquire();

            }

            else

            {

                // 失去输入设备

                g_KDIDev->Unacquire();

            }

           

            return 0;  

        }

       

    ...

}

 

DirectInput的初始化过程也放在OpenGL的初始化过程中,如果DirectInput初始化不成功,就返回失败。

 

int glInit(GLvoid)     

{

 

    if (!DXInit())                  // 初始化DirectInput

    {

        return FALSE;               //失败,返回

    }

 

    ...

 

    return TRUE;       

}

 

DirectInput的关闭也整合在OpenGL的关闭过程中。

 

void glShutdown(GLvoid)                            

{

……

    DXShutdown();       //关闭DirectInput

}

 

DirectInput设备全部就绪后,就可以获取输入数据了,GetDeviceState完成对设备输入数据的记录,这个过程在程序的主循环流程glMain中。

 

BYTE    buffer[256];           

int glMain(GLvoid)

{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

 

    //获取输入设备的数据,保存在buffer

    HRESULT hr = g_KDIDev->GetDeviceState(sizeof(buffer), &buffer);

 

    //对键盘输入进行处理

    if(!KeyPressed())

        return FALSE;

 

gluLookAt(

g_Camera.m_vPosition.x, g_Camera.m_vPosition.y, g_Camera.m_vPosition.z,         g_Camera.m_vView.x, g_Camera.m_vView.y, g_Camera.m_vView.z,

g_Camera.m_vUpVector.x,g_Camera.m_vUpVector.y,g_Camera.m_vUpVector.z);

 

    //绘制表示地面的网格

    Draw3DSGrid();

 

    //创建四个金字塔

    CreatePyramid(-6, 0, 6, 1, 1);

    CreatePyramid(6, 0, 6, 1, 1);

    CreatePyramid(6, 0, -6, 1, 1);

    CreatePyramid(-6, 0, -6, 1, 1);

 

    SwapBuffers(g_hDC);

    return TRUE;

}

 

对键盘的处理就很简单了,这里我们需要程序做出反应的只有6个键:F1ESC和四个方向键。

 

int KeyPressed()

{

    if(buffer[DIK_ESCAPE])  //这里的值都是DIK_***,而不是VK_***

        return FALSE;

   

    if (buffer[DIK_F1])         //F1切换全屏和窗口模式

    {

        buffer[DIK_F1]=FALSE;

        glShutdown();          

        fullscreen=!fullscreen;            

        if (!InitInstance(WIDTH, HEIGHT, BITS))

        {

            return FALSE;  

        }

    }

   

    if(buffer[DIK_UP])                  //前进

    {

        g_Camera.MoveCamera(kSpeed);

    }

   

    if(buffer[DIK_DOWN])                //后退

    {

        g_Camera.MoveCamera(-kSpeed);  

    }

   

    if(buffer[DIK_LEFT])                //向左转

    {

        g_Camera.RotateView(kSpeed, 0, 1, 0);  

    }

 

    if(buffer[DIK_RIGHT])               //向右转

{

        g_Camera.RotateView(-kSpeed, 0, 1, 0); 

    }

   

    return TRUE;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值