- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF82:Ogre
Материал из Linuxformat.
Разработка 3D-игры |
---|
|
Видеокарта Nvidia GeForce 7800, используемая для разработки этого руководства, была любезно предоставлена MSI. Спасибо, ребята!
Содержание |
Ogre Создаем ландшафт для 3D-игры
ЧАСТЬ 1 Пол Хадсон начинает это долгожданное руководство с описания ландшафта.
Что приятно в написании статей для Linux Format так это необходимость расширять собственный кругозор для самой возможности создания и описания новых проектов для ваших тренировок. Можете себе представить, к примеру, как я был озадачен, когда меня попросили заняться серией статей о программировании 3D-игр. Не то что я не люблю писать о Linux: на самом деле, очень люблю. Но больше я, конечно, люблю играть в игры, потому как игры — это весело по определению. И вдруг оказалось, что веселее, чем играть в игры, только одно (по крайней мере, на компьютерах): их создавать! Обладание неограниченной исполнительной властью над жизнью проекта, несущего счастье миллионам[1].
Поэтому мы, в Лаборатории LXF, составили базовое руководство по проектированию, разработке и выпуску вашей собственной 3D-игры. У вас, вероятно, уже руки чешутся поработать, но не спешите — в данной статье я сначала поведаю об игре вообще и о программах с библиотеками — необходимом инструментарии для ее разработки, а уж потом напущу вас на решение библейски-первозданной задачи: наколдовать для игры небо и землю.
Барьер номер один
Хотя большинство стрелялок от первого лица проходят по формуле «целься, стреляй, беги, опять стреляй», они все-таки пытаются обставиться хоть каким-то сюжетом. И вот наш сюжет, в виде краткого представления персонажа:
Десять лет назад лихой спецназовец был приговорен судом к тюремному заключению за преступление, которое не совершал, но быстренько сбежал из-за колючей проволоки к нелегалам Сан-Франциско. Сейчас, будучи все еще в розыске, он работает солдатом удачи. Если у вас проблемы, и помочь вам некому, сумейте отыскать и нанять... Чеда!
Наш герой Чед приговорен к повешению и находится в бегах. Игра будет патетически называться «Висельник Чед», хотя в идеале наш герой избежит казни, изувечив всех на своем пути. Он будет бороться против плохих парней (в основном против тех, что для нас заготовили разработчики Ogre), преодолевая всяческие трудности, для чего потребуется настоящий героизм (но главным образом пальба). Кроме того, он задействует арсенал тяжелого боевого оружия, позволив нам поупражняться в спецэффектах.
Заинтересовались? Еще бы!
Прежде чем браться за написание кода — или даже за установку нужного для кодирования программного обеспечения, надо сообразить, что именно вы хотите написать (дико извиняюсь перед программистами экстремалами). Поэтому я задам особенности предполагаемой игры: что она будет делать, как выглядеть, как в нее играть, и так далее.
- Это будет стрелялка от первого лица (First-Person Shooter, FPS). Я знаю, существуют тысячи FPS, а все потому, что их сравнительно лег ко порождать, они дают разгуляться фантазии и нуждаются в безумно красивой графике. Я не намерен ничего придумывать за вас, но надеюсь создать игру, простую в разработке и классную на вид!
- Это будет однопользовательская игра с неким подобием искусственного интеллекта, чтобы добавить сложности.
- Действие будет происходить на обширной открытой местности, игроки будут ее исследовать. Для разнообразия, они смогут передвигаться на транспорте, а может, и входить в помещения. Так игра будет больше похожа на Quake.
- Игра будет написана на С++, по принципу «лишь бы работало». За совершенством гнаться не станем. Место в журнале ограничено, и я лучше покажу вам 5 строк нормально работающего кода, чем 50 строк идеального.
- Игра будет кросс-платформенной. Мы будем разрабатывать ее в SUSE 10.1, но она должна работать и на любом другом дистрибутиве Linux. Будет здорово, если игра также будет работать в Windows и OS X, но это не главная наша цель.
- Игра будет выпущена под лицензией GPL.
Напоминаю, что это руководство по программированию 3D-игр, а не по С++, математике или Blender. Поэтому я сфокусируюсь на 3D-графике, прихватывая готовые модели и элементы игры везде где только можно. Если вы знаете Blender — прекрасно: сможете создать собственное творение. Если нет, не переживайте: все, что вам нужно — способность программировать.
Наша цель состоит в создании законченной игры. Для этого мы воспользуемся графическим движком Ogre 3D и SDL для аудио и прочих нужд. Однако потребуется еще заполнить немало пробелов, оставленных SDL и Ogre.
Список требований
Теперь вы знаете, что мы хотим запрограммировать, поэтому необходимо привести в боевую готовность вашу систему. Для программирования потребуется установить следующее ПО (заметим, что здесь указаны лишь минимально допустимые версии; более новые версии будут предпочтительнее):
- Automake 1.6
- Autoconf 2.5
- make 3.8
- libtool 1.4
- pkg-config 0.17.2
- GCC 3.4
- g++ 3.4
- cpp 3.4
Приведенные названия должны совпадать с теми, что вы найдете в менеджере пакетов вашего дистрибутива. Исключение может составить pkg-config, иногда называемый pkgconfig.
Так как мы собираемся работать с играми, понадобятся дополнительные пакеты, а именно:
- SDL 1.2.9
- SDL_Mixer 1.2.6
- Mesa
- FreeType2 2.1
- libpng
- libmng
- libtiff
- libjpeg
Как и в первом случае, все вышеозначенные библиотеки можно найти в менеджере пакетов. Проверьте, что вы устанавливаете как саму библиотеку, так и версию для разработчика, иначе вы сможете только запускать игру, но не разрабатывать свою собственную. Например, помимо пакета SDL существует пакет SDL-devel (или SDLdev), который также надо установить.
Теперь нам надо установить действительно особые программы, предназначенные для разработки игры. Этот список гораздо короче — и, возможно, не все они найдутся в вашем менеджере пакетов. Нам понадобятся следующие:
- zziplib 0.12
- DevIL 1.5
- Ogre 3D 1.2
- Приличный драйвер видеокарты
Мы разместили все эти пакеты на диске (включая последние драйвера Nvidia и ATI для Linux) и расскажем, как их установить. Начнем с драйвера видеокарты. У меня MSI Nvidia GeForce 7900, поэтому весь код, описанный здесь, будет работать с картами Nvidia.
Убойный графический драйвер
Чтобы установить драйвер Nvidia, нажмите Ctrl+Alt+F1 — попадете в терминал. Переключитесь в суперпользователя и наберите init 3, что-бы завершить работу X. Далее скопируйте драйвер с нашего диска в свой домашний каталог и запустите sh ./NVIDIA-Linux-x86-1.0-8756. Запустится программа установки, с текстовым интерфейсом, и вас попросят принять лицензионное соглашение. Если драйвер у вас уже был, вам надо нажать Yes, чтобы его удалить. Может оказаться, что для вашего ядра не найдется скомпилированного интерфейса, поэтому нажмите Yes, чтобы поискать драйвер на сайте Nvidia. Если его там нет, снова нажмите OK и скомпилируйте собственный драйвер. Наконец, будет предложено отредактировать за нас файл настроек X — соглашайтесь, да не забудьте потом проверить файл /etc/X11/xorg.conf и убедиться, что используется драйвер ‘nvidia’ (а не ‘nv’ или, того хуже, ‘vesa’). По завершении установки наберите init 5 — вернетесь обратно в X. Откройте терминал и запустите glxgears. Секунд через пять вы увидите результаты тестирования — если результат меньше 1000 кадров в секунду, это сильно повредит нашей игре.
Для более продвинутой работы с графикой можете установить библиотеку Cg (здесь некогда про нее рассказывать, но вреда от нее всяко не будет). ‘Cg’ — сокращение от ‘C for Graphics’, а цель библиотеки — облегчить создание продвинутых визуальных эффектов. Вы можете скачать инструментарий Cg со страницы Nvidia для разработчиков по адресу http://developer.nvidia.com/page/cg_main.html. Процесс ее установки лишен особого полета: скопировать в домашний каталог в подкаталог Cg, извлечь с помощью tar xvfz Cg-1.4.1_x86.tar.gz, переключиться в суперпользователя и запустить cp -R usr /.
Установка zziplib — тоже всего-навсего извлечение и запуск ./configure, make и make install. Если кому интересно, zziplib предоставляет быстрый и удобный способ манипулирования zip-файлами, а именно в них Ogre хранит множество своих ресурсов. Далее идет DevIL — мультиплатформенная библиотека для работы с изображениями, используемая Ogre. Она находится на диске к журналу, так что скопируйте ее в ваш домашний каталог и запустите
tar xvfz DevIL-1.6.8-RC1-src.tar.gz cd DevIL-1.6.8-RC1 ./configure make su make install exit
Теперь осталось главное событие: Ogre. Скопируйте его в домашний каталог с диска и наберите:
tar xvfj ogre-linux_osx-v1-2-0.tar.bz2 cd ogrenew ./bootstrap ./configure (или ./configure --with-platform=GLX если используется Nvidia) make su make install ldconfig exit
Список требований выполнен — можно начинать делать игру, ура!
Время кодировать
Настал долгожданный момент первой «вылазки» в С++ ! Наш первый урок — не простое введение или руководство по установке: мы собираемся написать сердцевину нашего движка. Цель урока — создание некого ландшафта, по которому можно перемещаться с помощью мыши, и неба над ним. Большая часть кода этого урока состоит из основных начальных установок Ogre: инициализации движка, обработки ввода и т. д. В следующих выпусках уже добавятся красивости — например, управление с клавиатуры, туман и свет, анимация и спецэффекты; а пока займемся черновой работой.
Вооружившись этими данными, откройте текстовый редактор и настучите следующий код в chad.h, основной заголовочный файл нашего игрового класса:
#include "Ogre.h" #include "SDL/SDL.h" #include "SDL/SDL_mixer.h" using namespace Ogre; #include "chadframelistener.h" class CChadGame { public: CChadGame(); ~CChadGame(); bool loadConfig(); void initialise(); int run(); void createScene(); Root* m_Ogre; EventProcessor* m_EventProcessor; CChadFrameListener* m_FrameListener; SceneManager* m_SceneMgr; Camera* m_Camera; Viewport* m_Viewport; };
Первые три выражения #include включают наши стандартные библиотеки, хотя SDL мы пока трогать не будем. Четвертый #include предназначен для обработчика кадра — скоро мы к нему вернемся. Далее идет главный класс нашей игры, ответственный за большую часть ее организации. Не буду выпендриваться с объектно-ориентированным программированием, хотя как раз организации объектный подход и способствует — как я уже сказал, нам важно не изящество кода, а удобство игры; итак, не удивляйтесь, что я браво игнорирую инкапсуляцию объектов ради экономии места!
Класс CChadGame содержит обработчик событий и обработчик кадра, наш менеджер сцены (отслеживающий все объекты), камеру (позицию игрока) и область просмотра (то, что мы видим на экране). Позже в нем появится информация об игроке, очках, картах и многое другое, но сейчас все предельно просто.
Большая часть работы совершается обработчиком кадра и менеджером сцены, во многом благодаря Ogre. Задача нашего класса CChadGame состоит в том, чтобы установить каждую сцену и обрабатывать любые изменения, например, передвижение игроков. Однако менеджер сцены параллельно будет отслеживать все объекты в нашей игре и обеспечивать их корректную прорисовку (с применением оптимизации). Нашу заботу о вводе данных от пользователя любезно берет на себя обработчик событий Ogre. Затем эта информация посылается в обработчик кадра, который переваривает изменения.
Реализация класса CChadGame находится в файле chad.cpp на нашем диске, но он слишком велик, чтобы напечатать его здесь, поэтому отразим только основные моменты: конструктор (CChadGame()) и функцию initialise().
CChadGame::CChadGame() { m_Ogre = new Root; this->loadConfig(); if(!m_Ogre->showConfigDialog()) return; m_Ogre->initialise(true, "Hanging Chad"); this->initialise(); this->createScene(); }
Root — базовый класс Ogre и родитель остальных наших объектов из Ogre. Именно Root отвечает за прорисовку и передачу обратных вызовов к обработчику кадров. Именно объект Root показывает диалог конфигурации пользователю (через вызов m_Ogre->showConfigDialog()), а также вежливо завершает игру, когда мы сигнализируем, что с нас хватит. Первое, что мы создаем, и последнее, что удаляем — объект Root.
В функции CСhadGame::initialise() настраиваются менеджер сцены, камера, область просмотра, обработчик событий и обработчик кадра. В ней же происходит вызов функции InitialiseAllResourcesGroups(), загружающей все ресурсы Ogre. Я одолжил стандартные файлы конфигурации (и их загрузчик, CChadGame::loadConfig()) из Ogre SDK и немного их подправил, чтобы они работали в нашей игре. Загрузчик конфигурации только читает текст: разборки синтаксиса не происходит, пока не вызовется initialiseAllResourcesGroups(). Если вы забудете вызвать эту функцию, то наверняка столкнетесь с проблемами!
Делай, что я сказал…
Две строчки кода для генерации ландшафта набрать легко, но в ответ на них Ogre сгенерировал для нас аж 28000 треугольников. За крутыми строками упрятана напряженная работа – наша тестовая машина показала в среднем 600 кадров в секунду, а на менее мощном компьютере результат мог быть и хуже.
Здесь та же проблема, что и у интегрированных сред разработки, поддерживающих сворачивание кода. Вы видите строчку вызова и думаете: «Ага, тебя-то мне и надо», копируете ее и вставляете сразу в нескольких местах. А потом замечаете, что в свернутом коде на самом деле 1000 строк, и вы чуть ли не удвоили объем своей программы!
В Ogre, добавление одной строки может вылиться в тысячи, а то и миллионы новых треугольников, и всех их надо отобразить на экране. Поэтому будьте осторожны с поправками!
Осталось написать обработчик кадра, в который будут посылаться и обрабатываться события от Ogre. Здесь интерес представляют три функции, одна из которых говорит почти сама за себя. Это конструктор, и он сохраняет ссылку на устройство ввода, камеру и менеджера сцены для последующего использования.
Другая интересная функция — frameStarted(), вызываемая перед тем, как Ogre начнет обсчитывать кадр. Она перехватывает ввод и проверяет необходимость ответа на ввод от пользователя. В данный момент это значить «если нажали Escape, то возвратить false». Это значение завершит цикл прорисовки Ogre, и произойдет выход из игры. Третья функция — mouseMoved(), дублированная также в mouseDragged(); она вызывается при любом перемещении мыши, когда нам необходимо повернуть камеру в соответствии с параметрами перемещения.
Оставьте пока функцию createScene() пустой — и ваша программа, наконец, готова к сборке. Однако вручную эту работу выполнять довольно тягостно, поскольку необходимо подключить библиотеки SDL и Ogre. Поэтому обратимся к Makefile, чтобы вы могли набрать make и наслаждаться, любуясь, как вкалывают за вас. Наберите следующий текст в файл Makefile — но очень аккуратно, потому что пробелы — это на самом деле символы табуляции!
DEFINES = LIBS = Ogre CXX = g++ CXXFLAGS = $(shell pkg-config --cflags $(LIBS)) $(DEFINES) -I/home/paul/Desktop/Ogrenew/Samples/Common/include LD = g++ LDFLAGS = $(shell pkg-config --libs $(LIBS)) -lSDL -lSDL_mixer -lpthread all: $(CXX) $(CXXFLAGS) $(LDFLAGS) -o chad chad.cpp clean: rm -f chad
Время поколдовать
Все самое нудное позади, ваша «игра» (скопированная с диска к журналу) должна скомпилироваться и запуститься — просто наберите make. Когда она запустится, возникнет окно настроек Ogre (см. рис. 1). Рядом с пунктом Select Render вы увидите Select One. Нажав на него, вы получите список вариантов, доступных в вашей системе, где почти наверняка фигурирует только OpenGL Rendering Subsystem. Ogre все равно, как отрисовывать изображения, поэтому под Windows ваша игра может использовать DirectX.
Окно настроек позволяет сделать многое, например, установить разрешение экрана или выбрать полноэкранный режим; и Ogre автоматически сохранит ваш выбор в Ogre.cfg для дальнейшего употребления.
Настроив графику, нажмите Accept, и ваша «игра» начнется. Я написал слово «игра» в кавычках, потому что на данном этапе это пустой экран — зрелище не шибко захватывающее, но по крайней мере видно, что код работает! И теперь можно применить возможности Ogre: создадим пейзаж с помощью всего одной строки кода. Не бойтесь, она много короче тысячи символов.
Вот она, просто вставьте ее в вызов createScene():
m_SceneMgr->setWorldGeometry("terrain.cfg");
Перекомпилируйте и запустите ваше приложение. Вы увидите нечто похожее на рис. 2 — холмистый ландшафт. Свет, правда, прилип к текстуре, но даже так все выглядит вполне мило — это благодаря файлу terrain.cfg, который загружает уже существующие текстуры из Ogre SDK. Каталог, из которого берутся текстуры, получается из каталога установки Ogre вашей машины, а загружаются они в файле resource. cfg, который вы можете настроить по своему усмотрению (или позволить другим это делать), причем для этого не придется переписывать ни строчки кода.
Если вы все еще не пришли в восторг, добавим немного неба. Небо предусмотрено в трех моделях: плоское, коробка или купол (в порядке возрастания степени реализма и, соответственно, потребления ресурсов). Плоское небо (по сути, многоугольник, висящий над игроком) почти не нагружает GPU, но выглядит убого — наш ландшафт не упрятывает линию горизонта, и сразу заметно, что оно именно плоское. Модель-коробка ликвидирует данный недостаток, помещая игрока внутрь куба и отображая небо на каждую его грань. Потребление ресурсов шестикратно возрастает, зато уж небо есть везде. У последней модели — купола — отсутствует «дно», а на «покрышку» для пущей иллюзии натянута текстура. Отсутствие дна может создать проблему, если игрок глянет вниз, но там уже есть ландшафт, так что все в порядке.
Код для невероятно сложной иллюзии выглядит так:
m_SceneMgr->setSkyDome(true,"Examples/CloudSky");
Да, да, это все! — теперь перекомпилируйте и запустите игру. Наслаждайтесь. Используйте мышь, чтобы оглядеться вокруг — вы увидите довольно милую картинку, как на рис. 3. Важнее всего, что наш небольшой продукт не так плох для начала! Теперь осталось добавить клавиши WASD для перемещения, немного тумана, пару источников света, злодеев и физи… Стоп, я, кажется, забежал впереди паровоза. Итак, вы получили краткое и несложное руководство для ознакомления с Ogre — и вас ожидает еще много интересного.
- ↑ Миллионам? Да, люблю метить высоко. Поэтому ничего не замечаю, пока не грохнусь.
Категории: Учебники | Игрострой | Ogre | Пол Хадсон