3. Ogre3D: Базовое приложение Ogre3D
Добро пожаловать в нашу первую статью, касающуюся непосредственно функционала Ogre3D. Наш диалог об этом бесплатном движке мы начнем с разбора его базового приложения. Базовое приложение – это та точка, с которой начинается построение вашей игры. Базовое приложение Ogre идет в составе OgreSDK и распространяется под бесплатной лицензией. Код поставляется в виде двух файлов — это хэдер BaseApplication.h и исходник BaseApplication.cpp.
Из чего состоит обычный проект?
Для начала давайте посмотрим из каких ключевых частей состоит обычный проект приложения под Windows. Любой проект C++ начинается с главной функции main, и проект под Windows не является исключением. Декларация функции main под Windows отличается от декларации под Linux. Это не создает большого количества проблем, так как суть одна и та же — у нас есть функция main, которая получает на вход строковые аргументы и их количество.
Две главные задачи, которые решает функция main — это настройка окна и создание главного объекта приложения. Это довольно распространенная и типичная схема построения приложения игры. При настройке окна вы указываете его размеры, основные параметры, название окна, стиль и передаете указатель на соответствующие процессоры эвентов.
После настройки окна обычно создается главный объект приложения – это объект, который несет в себе все основные классы игры. Далее у этого главного объекта может быть вызван метод initialize или что-либо в этом духе, для того чтобы приложение зарезервировало все необходимые для своей работы ресурсы.
Туда, например, может передаваться хэндлер окна для создания окна DirectX или OpenGL, какие-либо внешние ресурсы и т.д.
Вторая важная часть среднестатистического проекта – это процессор эвентов. Процессор эвентов – это способ передать внешние события Windows в приложение. Процессор эвентов обычно представлен одним большим методом со специфической декларацией. Внутри этого метода обычно располагается большой switch, который разбирает произошедшее событие.С помощью таких процессоров мы можем, например, передавать в игру ввод пользователя. Пользователь создает событие, например, перемещая мышь или нажимая клавиши, Windows перехватывает эти события и передает их в приложения. Приложения по имеющемуся указателю вызывает процессор эвентов. Он определят тип события и вызывает соответствующий метод главного объекта приложения – а внутри игры вы самостоятельно обрабатываете произошедшее событие. Основная задача базового приложения Ogre – скрыть эту повторяющуюся рутинную работу от пользователя.
Base Application
Как мы выяснили, Base Application — это класс приложения Ogre, который инкапсулирует всю рутинную работу приложения. Этот класс условно можно разделить на три ключевые части — основные методы приложения, каллбеки ввода и защищенная часть.
Для того чтобы воспользоваться этим классом, мы должны создать его потомка. Большинство методов Base Application являются виртуальными, что позволяет перегрузить нам лишь те из них, которые необходимы нам в данном приложении.
Рассмотрение этого класса мы начнем с первой группы методов.
virtual void go(void); virtual bool setup(); virtual bool configure(void); virtual void chooseSceneManager(void); virtual void createCamera(void); virtual void createFrameListener(void); virtual void createScene(void) = 0; // Override me! virtual void destroyScene(void); virtual void createViewports(void); virtual void setupResources(void); virtual void createResourceListener(void); virtual void loadResources(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); |
Как вы можете заметить, большинство из этих методов несут подготовительную функцию. Среди этих методов вы можете отметить выбор сцен менеджера, создание камеры, создание сцены, уничтожение сцены, создание вьюпортов и подготовку ресурсов.
Создание и уничтожение сцены являются ключевыми методами. Вам необходимо перегрузить эти методы в наследники Base Application, для того чтобы подготовить сцену вашего приложения и освободить ресурсы после его работы. Остальные методы существуют на случай, если вместо стандартных вам нужны специфичные свойства приложения — например, если вам необходимо вместо обычной камеры иметь камеру «рыбий глаз», вы можете перегрузить соответствующий метод и создать необходимую вам камеру.
Помимо методов подготовки приложения мы видим два специфичных метода. Первый из них – метод go() — сиглализирует о запуске приложения – после создания главного объекта приложения Вы вызываете этот метод и приложение начинает свой рабочий цикл. Также необходимо отдельно отметить метод frameRendering(…). Этот метод позволяет нам подготовиться к отрисовке следующего кадра — например, обновить анимацию, просчитать следующий тик игровой механики и т.д. Этот метод является аналогом обычного метода Update, который вызывается перед отрисовкой кадра. В качестве параметров этому методу передается FrameEvent, в одном из полей которого вы можете найти время, прошедшее с момента отрисовки предыдущего кадра.
Следующая группа методов, условно называемая нами каллбеками ввода, позволяет нам среагировать на ввод пользователя в нашем приложении.
virtual bool keyPressed( const OIS::KeyEvent & arg ); virtual bool keyReleased( const OIS::KeyEvent & arg ); virtual bool mouseMoved( const OIS::MouseEvent & arg ); virtual bool mousePressed( const OIS::MouseEvent & arg,OIS::MouseButtonID id ); virtual bool mouseReleased( const OIS::MouseEvent & arg,OIS::MouseButtonID id ); |
Эта группа состоит из методов реакции на события клавиатуры и схожих методов реакции на события мыши. Помимо прочего, обработка мыши включает в себя метод mouseMoved , который позволяет отслеживать события перемещения мыши. Как только пользователь нажимает какую-нибудь клавишу, из внешней среды вызывается перегруженный вами метод keyPressed, в котором вы можете среагировать на это событие. Как только пользователь отпускает клавишу, вызывается метод keyReleased. Для мыши аналогичная пара mousePressed и mouseReleased. mouseMoved, как мы уже отметили, вызывается, когда пользователь передвинул мышь. В качестве параметров эти методы получают информацию о произошедшем событии. Например, какая клавиша была нажата или насколько была передвинута мышь.
Рядом с каллбэками ввода располагаются еще два метода реакции на внешние события
virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw); |
Перегрузив эти методы мы можем среагировать на события окна, в котором запущено наше приложение.
Следующая важная часть класса Base Application – это его protected члены.
Ogre::Root* mRoot; Ogre::Camera* mCamera; Ogre::SceneManager* mSceneMgr; Ogre::RenderWindow* mWindow; Ogre::String mResourcesCfg; Ogre::String mPluginsCfg; |
// OgreBites OgreBites::SdkTrayManager* mTrayMgr; OgreBites::SdkCameraMan* mCameraMan; OgreBites::ParamsPanel* mDetailsPanel; bool mCursorWasVisible; bool mShutDown; |
//OIS Input devices OIS::InputManager* mInputManager; OIS::Mouse* mMouse; OIS::Keyboard* mKeyboard; |
Ключевое слово — protected позволяет вам использовать эти компоненты в потомках класса. Среди них вы можете отметить камеру, менеджер сцены, корневой узел сцены и т.д. Об этих компонентах мы поговорим в следующих статьях цикла.
Для правильной работы с приложением Ogre вам необходимо создать потомка класса Base Application и перегрузить необходимые вам методы. Если вы хотите оставить способ работы метода по умолчанию — не перегружайте его. Например, на ранних стадиях проекта бывает полезно оставить предлагаемую по умолчанию работу мыши и клавиатуры. Это позволит иметь базовую навигацию в сцене до тех пор, пока вы не задатите собственные способы управления сценой. Не забывайте о декорации методов. Например, если вы хотите расширить способ работы мыши, добавьте дополнительную логику в перегруженный метод, после чего вызовите метод базового приложения.
Заполнен: Ogre3D
