zoukankan      html  css  js  c++  java
  • CEGUI、DirectX和OIS结合 冷夜

    OIS即面向对象的输入系统(Object-Oriented Input System(OIS)

    OIS是一个面向对象的输入系统,理论上它可以支持任何输入设备,其中最主要的三类是键盘、鼠标和游戏控制器。OIS是一个开放源码的项目,你可以按你的要求定制它,以满足你的需求。

    下载地址:http://sourceforge.net/projects/wgois/

    主要过程:

    1.编译好OIS

    2.创建好windows窗口,初始化Directx和CEGUI

    3.初始化输入管理系统和输入设备

        HWND m_hWnd;
        OIS::InputManager *m_pInputManager;
        OIS::Mouse *m_pMouse;
        OIS::Keyboard *m_pKeyboard;
    
        OIS::ParamList pl;
        std::ostringstream windowHndStr;
        windowHndStr <<(size_t)hwnd;     // 窗口句柄
        pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));       // 传入窗口句柄                               
        pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_FOREGROUND"));    //前台模式,也就是说使用它的程序必须处于激活状态,
                                                                            //如果它失去焦点就会自动失去设备,在它重新获得焦点的时候必须重新获得设备使用权
    
        pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_NONEXCLUSIVE"));  // 允许其他程序使用,并且不会干扰其他应用程序的使用
    
        // 创建输入设备
        m_pInputManager = OIS::InputManager::createInputSystem( pl );
    
    
        //m_pInputManager=OIS::InputManager::createInputSystem((size_t)m_hWnd);
        m_pMouse = static_cast<OIS::Mouse*>(m_pInputManager->createInputObject( OIS::OISMouse, true));//第三个参数为真是为缓冲处理
        m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputManager->createInputObject( OIS::OISKeyboard, true ));

    首先我们先讲一个问题,就是 缓冲和非缓冲。

    缓冲输入就是说你每次的按键值都要先存入缓冲区,等程序有时间了就会去做相应的处理,意思说只要你按了某个键,电脑早晚都会给你做相应的事情,哪怕等到程序死机(如果这样,说明你很不幸哦!)。非缓冲就是程序现在有时间处理你的时候来问你,“有什么要做的没?“,如果这是你的鼠标键盘有任何时间的话,程序就做相应的处理,没有的话,不做任何处理,哪怕在这之前你按了鼠标或者键盘的某些键,程序也会忽略。它们的区别就是缓冲可以处理一切事件,但是需要缓冲,则比较慢,非缓冲可能会忽略某些信息,但是它不需要缓冲,处理速度要快一些。

    4.创建并设置监听类

    class GuiFrameListener:public OIS::MouseListener,public OIS::KeyListener
    {
    private:
        bool mShoutdownRequested; //结束标志
        HWND m_hWnd;
    
    public:
        GuiFrameListener(HWND hWnd)
        {
            m_hWnd=hWnd;
            mShoutdownRequested=true;
        }
    
        bool quit(const CEGUI::EventArgs &evt)
        {
            mShoutdownRequested=true;
            return true;
        }
    
    
        bool mouseMoved(const OIS::MouseEvent &evt);
        bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) ;
        bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id );
        bool keyPressed(const OIS::KeyEvent &evt );
        bool keyReleased(const OIS::KeyEvent &evt );
        void doNumKeyboard(OIS::KeyEvent &evt);
    };
        m_listener=new GuiFrameListener(m_hWnd);
        m_pMouse->setEventCallback(m_listener);
        m_pKeyboard->setEventCallback(m_listener);

    5.在循环函数中加入输入设备的接收数据接口

            m_pMouse->capture();
            m_pKeyboard->capture();

    6.OIS与CEGUI结合,主要是在监听类里的鼠标键盘响应函数中加入响应的injectXXXXX函数

    例如鼠标按下的:

    bool  GuiFrameListener::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) 
    {
        CEGUI::System::getSingleton().injectMouseButtonDown(convertOgreButtonToCegui(id));
        return true;
    }

    7.因为传入鼠标ID的时候 OIS::MouseButtonID和CEGUI::MouseButton是两个不同的枚举,所以要作下转换

    CEGUI::MouseButton convertOgreButtonToCegui(int buttonID)
    {
        switch (buttonID)
        {
        case OIS::MB_Left:
            return CEGUI::LeftButton;
        case OIS::MB_Right:
            return CEGUI::RightButton;
        case OIS::MB_Middle:
            return CEGUI::MiddleButton;
        default:
            return CEGUI::LeftButton;
        }
    }

    下面是完整的代码:

    头文件

    #ifndef _OISAPP_H_
    #define  _OISAPP_H_
    
    #include <windows.h>
    #include "OIS.h"
    #include"CEGUI.h"
    
    using namespace std;
    
    #ifdef _DEBUG
    
    #pragma comment( lib, "OIS_d.lib" )
    #else
    #pragma comment( lib, "OIS.lib" )
    #endif
    
    CEGUI::MouseButton convertOgreButtonToCegui(int buttonID);
    
    class GuiFrameListener:public OIS::MouseListener,public OIS::KeyListener
    {
    private:
        bool mShoutdownRequested; //结束标志
        HWND m_hWnd;
    
    public:
        GuiFrameListener(HWND hWnd)
        {
            m_hWnd=hWnd;
            mShoutdownRequested=true;
        }
    
        bool quit(const CEGUI::EventArgs &evt)
        {
            mShoutdownRequested=true;
            return true;
        }
    
    
        bool mouseMoved(const OIS::MouseEvent &evt);
        bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) ;
        bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id );
        bool keyPressed(const OIS::KeyEvent &evt );
        bool keyReleased(const OIS::KeyEvent &evt );
        void doNumKeyboard(OIS::KeyEvent &evt);
    };
    
    class OISApp
    {
    public:
        OISApp();
        ~OISApp();
    
        bool Init(HWND hwnd);
        void capture();
    public:
        HWND m_hWnd;
        OIS::InputManager *m_pInputManager;
        OIS::Mouse *m_pMouse;
        OIS::Keyboard *m_pKeyboard;
        GuiFrameListener *m_listener;
        
        
    };
    
    
    
    
    
    
    
    
    #endif

    cpp

    #include "oisApp.h"
    #include "publicFunc.h"
    
    
    CEGUI::MouseButton convertOgreButtonToCegui(int buttonID)
    {
        switch (buttonID)
        {
        case OIS::MB_Left:
            return CEGUI::LeftButton;
        case OIS::MB_Right:
            return CEGUI::RightButton;
        case OIS::MB_Middle:
            return CEGUI::MiddleButton;
        default:
            return CEGUI::LeftButton;
        }
    }
    ////////////
    OISApp::OISApp()
    {
    
        m_pInputManager=NULL;
        m_pMouse=NULL;
        m_pKeyboard=NULL;
        m_listener=NULL;
    
    }
    
    OISApp::~OISApp()
    {
        m_pInputManager->destroyInputObject(m_pMouse);
        m_pInputManager->destroyInputObject(m_pKeyboard);
        OIS::InputManager::destroyInputSystem(m_pInputManager);
        safeDele(m_listener);
    
    }
    
    bool OISApp::Init(HWND hwnd)
    {
        if(m_hWnd<=0)
        {
        printf("ERROR: m_hWnd <=0\n");
        return false;
        }
        m_hWnd=hwnd;
    
    
        OIS::ParamList pl;
        std::ostringstream windowHndStr;
        windowHndStr <<(size_t)hwnd;     // 窗口句柄
        pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));       // 传入窗口句柄                               
        pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_FOREGROUND"));    //前台模式,也就是说使用它的程序必须处于激活状态,
                                                                            //如果它失去焦点就会自动失去设备,在它重新获得焦点的时候必须重新获得设备使用权
    
        pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_NONEXCLUSIVE"));  // 允许其他程序使用,并且不会干扰其他应用程序的使用
    
        // 创建输入设备
        m_pInputManager = OIS::InputManager::createInputSystem( pl );
    
    
        //m_pInputManager=OIS::InputManager::createInputSystem((size_t)m_hWnd);
        m_pMouse = static_cast<OIS::Mouse*>(m_pInputManager->createInputObject( OIS::OISMouse, true));//第三个参数为真是为缓冲处理
        m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputManager->createInputObject( OIS::OISKeyboard, true ));
    
        m_listener=new GuiFrameListener(m_hWnd);
        m_pMouse->setEventCallback(m_listener);
        m_pKeyboard->setEventCallback(m_listener);
    
        // 设置鼠标移动范围,OIS默认范围为50*50
        RECT clientRect;
        GetClientRect(m_hWnd,&clientRect);
        //GetWindowRect(m_hWnd,&clientRect);
        m_pMouse->getMouseState().width =clientRect.right;
        m_pMouse->getMouseState().height = clientRect.bottom;
    
        ShowCursor(0); //隐藏系统鼠标指针
    
        return true;
    }
    void  OISApp::capture()
    {
        if (m_pMouse&&m_pKeyboard)
        {
            m_pMouse->capture();
            m_pKeyboard->capture();
        }
    }
    ///////////////////////////
    
    
    bool GuiFrameListener::mouseMoved(const OIS::MouseEvent &evt)
    {
        //CEGUI::System::getSingleton().injectMouseMove(evt.state.X.rel,evt.state.Y.rel);
        RECT clientRect;
        GetClientRect(m_hWnd,&clientRect);
        //GetWindowRect(m_hWnd,&clientRect);
        int width =clientRect.right;
        int height = clientRect.bottom;
        int curx=evt.state.X.abs;
        int cury=evt.state.Y.abs;
        if (curx>0&&curx<width&&cury>0&&cury<height)
        {
            //ShowCursor(0); //隐藏系统鼠标指针
            CEGUI::MouseCursor::getSingleton().show();
            CEGUI::System::getSingleton().injectMousePosition(curx,cury);
        }else
        {
            CEGUI::MouseCursor::getSingleton().hide();
        }
        
        return true;
    }
    
    bool  GuiFrameListener::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) 
    {
        CEGUI::System::getSingleton().injectMouseButtonDown(convertOgreButtonToCegui(id));
        return true;
    }
    
    bool  GuiFrameListener::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id )
    {
        CEGUI::System::getSingleton().injectMouseButtonUp(convertOgreButtonToCegui(id));
        return true;
    }
    void GuiFrameListener::doNumKeyboard(OIS::KeyEvent &evt)
    {
        switch (evt.key)
        {
        case OIS::KeyCode::KC_NUMPAD0:
            {
                evt.text=48;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD1:
            {
                evt.text=49;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD2:
            {
                evt.text=50;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD3:
            {
                evt.text=51;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD4:
            {
                evt.text=52;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD5:
            {
                evt.text=53;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD6:
            {
                evt.text=54;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD7:
            {
                evt.text=55;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD8:
            {
                evt.text=56;
            }
            break;
        case OIS::KeyCode::KC_NUMPAD9:
            {
                evt.text=57;
            }
            break;
        }
    }
    bool  GuiFrameListener::keyPressed(const OIS::KeyEvent &evt )
    {
        //if(evt.key==OIS::KC_ESCAPE)
        //{
        //    mShoutdownRequested=true;
        //    return true;
        //}
    
        OIS::KeyEvent cEvent=evt;
        doNumKeyboard(cEvent);
        CEGUI::System::getSingleton().injectKeyDown(cEvent.key);
        CEGUI::System::getSingleton().injectChar(cEvent.text);
    
        switch (evt.key)
        {
        case OIS::KC_ESCAPE: 
            mShoutdownRequested = true;
            break;
    
        case OIS::KC_UP:
        case OIS::KC_W:
    
            break;
    
        case OIS::KC_DOWN:
        case OIS::KC_S:
    
            break;
    
        case OIS::KC_LEFT:
        case OIS::KC_A:
    
            break;
    
        case OIS::KC_RIGHT:
        case OIS::KC_D:
    
            break;
    
        case OIS::KC_PGDOWN:
        case OIS::KC_E:
    
            break;
    
        case OIS::KC_PGUP:
        case OIS::KC_Q:
    
            break;
        }
    
    
        return true;
    }
    
    bool  GuiFrameListener::keyReleased(const OIS::KeyEvent &evt )
    {
        CEGUI::System::getSingleton().injectKeyUp(evt.key);
        switch (evt.key)
        {
        case OIS::KC_UP:
        case OIS::KC_W:
            break;
    
        case OIS::KC_DOWN:
        case OIS::KC_S:
    
            break;
    
        case OIS::KC_LEFT:
        case OIS::KC_A:
    
            break;
    
        case OIS::KC_RIGHT:
        case OIS::KC_D:
    
            break;
    
        case OIS::KC_PGDOWN:
        case OIS::KC_E:
    
            break;
    
        case OIS::KC_PGUP:
        case OIS::KC_Q:
            break;
        }
    
    
        return true;
    }
  • 相关阅读:
    如何在linux系统中设置静态ip地址
    spring 学习
    java 反射机制和invoke方法
    CentoS7装机
    eclipse 添加jar包的方式
    No-args constructor for class does not exist. Register an InstanceCreator with G
    freemarker页面如何获取绝对路径basePath
    MySQL备份还原
    MySQL用户授权与权限
    CentOS7修改SSH远程连接端口
  • 原文地址:https://www.cnblogs.com/gamesky/p/2876410.html
Copyright © 2011-2022 走看看