OGRE实际应用程序[三]译

Posted on 2008-09-06 16:54 美洲豹 阅读(380) 评论(0)  编辑 收藏 引用

GUI

所有的游戏都有两个主要的"states": "GUI" "Game".然而,让CEGUI,OGRE一起工作还是要花费一点时间的。

首先,忘记CEGUI文章中的东西,那部分只有RTT (Render To Texture)值得看. 好些文章已经过期了,实际上,只需要四行代码把GUI导入Ogre窗口.

  在这之前,你先需要创建GUI。你可以简单地使用TaharezLook widget set. 它已经够用了。

对于我们的Simulator程序而言

首先,是一个欢迎界面,即Splash.接着,你会看到我们使用了多个scene managers. 为什么?因为没有一个Scene Manager适用于全部应用,可以在运行的时候转换也是很不错的。

CEGUI

使用CEGUILayoutEditor. Layout文件是整个GUI页面(sheet).你不需要手工的创建GUI。 导入后其使用方法与手工创建的一致。

Scheme可以在schemes/ 文件夹找到,它包含的imageset可以在imagesets/ 文件夹找到,其含义如下:每个widget (and widget state) TGA 图像的矩形框中的图片相映射. 查看这些文件你可以知道他们是如何协作的.

如前所述,你可以重新组织它们的文件结构,因为我们在初始化导入资源的时候提供了其位置,我们不需要跟踪它们,把这些交给Resource Manager好了。用CEGUILayEditor可以快速简单地创建界面。记住每一个.layout 文件都是一个单个的GUI sheet或页面的定义。对于你的GUI,对于每一个页面,你需要一个单独的Layout文件

最后,扩展名(.scheme, .layout, etc.) 只是为了方便。你可以更改其为你觉得方便的扩展名。

Handling GUI Events 处理事件响应

如果你对MFC熟悉,那么一定会知道要有事件的响应,比如按钮的响应等。在这里主要的区别是你的程序通过提供一个处理函数(handler method)来建立与GUI events(GUI事件)的联系。CEGUI在调用你的方法的过程中,传递了一个EventArgs对象,据此,你可以知道发生此事件的父窗口是什么(i.e.对于按钮按下的处理者,参数中你能够得到的窗口即是这个按钮).CEGUI中,你需要明白的是“所有东西都是一个窗口”.

一旦你了解了CEGUI,你会发现,它根本不处理输入。它不处理任何输入设备的信息,没有键盘,没有鼠标,没有任何输入。因此,它如何从这些输入设备中得到信息?你必须自己捕捉输入,比如使用OIS这种输入库。然后再把它提供给CEGUI,告诉它哪个按键被按下,哪个鼠标按钮被松开等信息。这一点可能通过injectMouseMove(), injectKeyDown(), injectKeyUp() 等方法实现. 非常的优雅,一旦你明白处理的流程,它对于你用各种不同的输入设备及输入方法均可处理。

UDIM是指CEGUI将整个窗口的宽与高设置为1.0. 那样的话,这个layout会占据整个渲染的窗口,而这正是我们想要的。如果想占据一部分,可以修改其值。在CEGUILayoutEditor编辑的图与游戏中看到的一样。

使用.layout文件的代码

下面是使用这个layout的代码,导入并显示:

        // setup GUI system
        mGUIRenderer = new CEGUI::OgreCEGUIRenderer(window, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, guiSceneMgr);
        mGUISystem = new CEGUI::System(mGUIRenderer);
        CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
        CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");
        mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
 
        CEGUI::FontManager::getSingleton().createFont("bluehighway.font");
        mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");
 
        // set the mouse cursor initially in the middle of the screen
        mGUISystem->injectMousePosition((float)window->getWidth() / 2.0f, (float)window->getHeight() / 2.0f);


对以上代码的一些提示:这里没有对文件目录的处理,由于我们使用了OgreCEGUIRenderer,因此ResouceManager已经帮我们处理了。

代码中的injectMousePosition()调用,是将鼠标放在屏幕的中央,所不同的是,这里使用的准确的位置而不是原来的(0.0-1.0)的映射的位置。

注册到CEGUI事件

提供CEGUI events事件的对应是直观的。代码如下:

                CEGUI::Window *win;
               m_win = CEGUI::WindowManager::getSingleton().getWindow(sheetName);
               win = m_win->getChild("cmdQuit");
               win->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(Quit_OnClick, this));

处理CEGUI事件

        bool GuiEventHandler_Main::Quit_OnClick(const CEGUI::EventArgs &args) {
               // initiate system shutdown (we do this by requesting a shutdown,
               // which eventually will stop the main loop)
               m_stateManager.requestStateChange(SHUTDOWN);
               return true;
        }
需要注意的是,这里面函数的写法是一致的。即返回值是bool,而参数都是CEGUI::EventArgs.

GUI与游戏中切换

这是前面初始化中showGui()的定义:

        if (window)
            window->removeAllViewports();
        if (guiSceneMgr)
               guiSceneMgr->removeAllCameras();
        else
               guiSceneMgr = ogre->getSceneManager(ST_GENERIC);
        if (sceneMgr)
            sceneMgr->removeAllCameras();
        camera = guiSceneMgr->createCamera("Main");
        camera->setPosition(0, 0, 300);
        camera->lookAt(0, 0, 0);
        window->addViewport(camera);

这里指出你如何在Ogre中切换SceneManagers. 首先,你需要移除一个窗口的所有视口,然后,移除一个场景管理器的所有摄像机,然后再选择另一个场景管理器,并为之创建摄像机及视口。

State Management 状态管理器

状态管理器? Does that come with Ogre?

它并在Ogre中,你可以自己写一个,这可以使输入对不同的状态进行分发。在这里,我们有STARTUP, SHUTDOWN, GUI and NORMAL这几个状态,每个程序中需要的状态可能不一样。


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


posts - 15, comments - 2, trackbacks - 0, articles - 29

Copyright © 美洲豹