[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Игровые движки » IrrLicht Engine » Туториал №18: SplitScreen
Туториал №18: SplitScreen
MerGC_TeamДата: Четверг, 03.04.2014, 18:14 | Сообщение # 1
Веселый админ
Группа: Администраторы
Сообщений: 32
Статус: Оффлайн
В этом туториале мы узнаем как разделить экран (например, для игр-гонок) в IrrLicht Engine. Мы создадим область проосмотра разбитую на 4 части, с 3 фиксированными камерами и 1 контролируемой пользователем.

Ok, пора начинать с хедеров (я думаю, что особо нечего сказать насчёт этого)
Код
#include < irrlicht.h >
#include "driverChoice.h"

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif

//Пространства имён движка
using namespace irr;
using namespace core;
using namespace video;
using namespace scene;


Теперь мы определим глобальные константы описывающие разрешение основного окна для использования при инициализации устройства и установки областей просмотра. В добавок мы установим глобальные переменные говорящие активен ли режим разбиения экрна..
Код
//Разрешение экрана
const int ResX=800;
const int ResY=600;
const bool fullScreen=false;

//по умолчанию используем режим SplitScreen
bool SplitScreen=true;


Теперь нам необходимы 4 указателя на наши камеры, которые будут созданы позже:
Код
//камеры
ICameraSceneNode *camera[4]={0,0,0,0};


В нашем event-receiver(получальщике событий) мы переключаем SplitScreen-переменные, каждый раз, когда пользователь нажимает клавишу "S". Все остальные события посылаются FPS камере.
Код
class MyEventReceiver : public IEventReceiver
{
         public:
                 virtual bool OnEvent(const SEvent& event)
                 {
                         //Клавиша S включает/выключает режим SplitScreen
                         if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
                    event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown)
                         {
                    SplitScreen = !SplitScreen;
                    return true;
                         }
                         //Послать все остальные события оставшимся 4 камерам
                         if (camera[3])
                    return camera[3]->OnEvent(event);
                         return false;
                 }
};


Ok, теперь основная функция: Во-первых, мы инициируем устройство, получаем менеджер сцены и Видеодрайвер, загружаем анимированный меш из .md2 и карту из .pk3. Так как это старый материал, я не буду объяснять каждый шаг. Нужно лишь позаботиться о позиции карты.
Код
int main(int argc, char** argv)
{
         // спросить пользователя о драйвере (OpenGL, DirectX и т.п.)
         video::E_DRIVER_TYPE driverType=driverChoiceConsole();
         if (driverType==video::EDT_COUNT) driverType = video::EDT_OPENGL;

         // Создать экземпляр EventReceiver(обработчика событий)
         MyEventReceiver receiver;

         // Инициализация движка
         IrrlichtDevice *device = createDevice(driverType,
                         dimension2du(ResX,ResY), 32, fullScreen,
                         false, false, &receiver);
         if (!device)
                 return 1;

         ISceneManager *smgr = device->getSceneManager();
         IVideoDriver *driver = device->getVideoDriver();

         // Загрузить модель
         IAnimatedMesh *model = smgr->getMesh("../../media/sydney.md2");
         if (!model)
                 return 1;
         IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model);
         // Загрузить текстуру
         if (model_node)
         {
                 ITexture *texture = driver->getTexture("../../media/sydney.bmp");
                 model_node->setMaterialTexture(0,texture);
                 model_node->setMD2Animation(scene::EMAT_RUN);
                 // отключаем освещение
                 model_node->setMaterialFlag(EMF_LIGHTING,false);
         }

         // Загрузить карту
         device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");
         IAnimatedMesh *map = smgr->getMesh("20kdm2.bsp");
         if (map)
         {
                 ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0));
                 // установить позицию
                 map_node->setPosition(vector3df(-850,-220,-850));
         }


Сейчас мы создадим 4 наши камеры. Одна смотрит на модель с фронта(спереди), одна сверху и одна сбоку. В добавок создадим FPS-камеру которая управляется пользователем.
Код
// Создать 3 фиксированные и 1 управляемую пользователем камеру
         // Вид спереди
         camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));
         // Вид сверху
         camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
         // Вид слева
         camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));
         // Вид контролируемый пользователем
         camera[3] = smgr->addCameraSceneNodeFPS();
         // ставим позицию камеры 3, чтобы не появилась в позиции модели
         if (camera[3])
                 camera[3]->setPosition(core::vector3df(-50,0,-50));


Создать переменную для подсчёта fps(фреймов в секунду) и скрыть мышь:
Код
// прячем указатель мыши
         device->getCursorControl()->setVisible(false);
         // тут будет подсчитывать fps
         int lastFPS = -1;


До сих пор было не так много нового материала! Только лишь созданием 4 камер, экран не будет разбит/разделён. Чтобы это сделать потребуется несколько шагов::
Установить область просмотра на весь экран
Создать новую сцену (очистить экран)
Следующие 3 шага повторяются для каждой области просмотра на разделённом экране
Установить область просмотра в необходимую вам область
Активировать камеру "связанную" с областью просмотра
Визуализировать(отрендерить) все объекты
Если у вас есть GUI:
Установить область просмотра на весь экран
Отобразить(отрисовать) GUI
End scene(команда конца отрисовки сцены в игровом цикле)

Звучит немного сложно, но вы увидите, что это не так:
Код
while(device->run())
         {
                 // //Установить область просмотра на весь экран и запустить сцену
                 driver->setViewPort(rect(0,0,ResX,ResY));
                 driver->beginScene(true,true,SColor(255,100,100,100));
                 // Если режим SplitScreen включен
                 if (SplitScreen)
                 {
                         // Активировать камеру 1
                         smgr->setActiveCamera(camera[0]);
                         // Установить область просмотра в первом квадрате (левый верхний)
                         driver->setViewPort(rect(0,0,ResX/2,ResY/2));
                         // Отрисовать сцену
                         smgr->drawAll();
                         // Активировать камеру 2
                         smgr->setActiveCamera(camera[1]);
                         // Установить область просмотра во втором квадрате (правый верхний)
                         driver->setViewPort(rect(ResX/2,0,ResX,ResY/2));
                         // Отрисовать сцену
                         smgr->drawAll();
                         // Активировать камеру 3
                         smgr->setActiveCamera(camera[2]);
                         // Установить область просмотра в 3 квадрате (левый нижний)
                         driver->setViewPort(rect(0,ResY/2,ResX/2,ResY));
                         // Отрисовать сцену
                         smgr->drawAll();
                         //Set viewport the last quarter (right bottom)
                         driver->setViewPort(rect(ResX/2,ResY/2,ResX,ResY));
                 }
                 // Активировать камеру 4
                 smgr->setActiveCamera(camera[3]);
                 // Отрисовать сцену
                 smgr->drawAll();
                 driver->endScene();


Как вы вероятно можете видеть, изображение рендерится для каждой области просмотра по отдельности. Это значит, что будут серьёзные потери производительности при выполнении рограммы. Ok, если вы спросите "Как я должен установить область просмотра, чтобы получить тот или иной экран?", без паники. Это действительно просто: В ф-ции вы создаёте прямоугольник определяя 4 координаты:
X-координата левого верхнего угла
Y-координата левого верхнего угла
X-координата правого нижнего угла
Y-координата правого нижнего угла

То есть, если вы желаете разбить экран на 2 области просмотра вы могли бы задать следующие координаты:
1-ая область просмотра: 0,0,ResX/2,ResY
2-ая область просмотра: ResX/2,0,ResX,ResY

Если вы поняли не в полной мере, просто поиграйте с этим примером чтобы понять что происходит в ответ на ваши действия.

Теперь мы просто посмотрим текущий fps и выключим движок, когда пользователь захочет:
Код
// получить и отобразить fps
                 if (driver->getFPS() != lastFPS)
                 {
                         lastFPS = driver->getFPS();
                         core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: ";
                         tmp += lastFPS;
                         tmp += ")";
                         device->setWindowCaption(tmp.c_str());
                 }
         }
         // Удалить устройство
         device->drop();
         return 0;
}


Вот и всё! Просто откомпилируйте и поиграйте с программой. Примечание: Нажимая клавишу "S" вы можете включать и выключать режим splitscreen.
 
Форум » Игровые движки » IrrLicht Engine » Туториал №18: SplitScreen
  • Страница 1 из 1
  • 1
Поиск: