Создание игрового движка
Разработка трехмерной обучающей игры. Игровой Движок как центральный программный компонент компьютерных игр или других интерактивных приложений с графикой, обрабатываемой в реальном времени. Проектирование архитектуры программного обеспечения игры.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 05.08.2011 |
Размер файла | 768,5 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Введение
Компания «DeeProSoft» получила проект от ЗАО «Уралвагонзавод» на разработку трехмерной обучающей игры целевой аудиторией которой являются школьники старших классов. Жанр игры - квест. Квест-- один из основных жанров компьютерных игр, требующих от игрока решения умственных задач для продвижения по сюжету. Сюжет может быть предопределённым или же давать множество исходов, выбор которых зависит от действий игрока[11]. Игроку предоставляется полная свобода перемещения по смоделированной трехмерной территории завода, возможность зайти в любой цех. Игрок будет действовать от первого лица, т.е. вид из глаз действующего героя. Смысл игры заключается в выполнение реальных заданий связанных с работой станков и прокатных станов. Параллельно игроку будет в ненавязчивой форме преподноситься обучающая информация. Основная цель данного проекта в привлечение новых кадров на завод, а так же - имиджевая составляющая завода. На подряде этого проекта от «Уралвагонзавод»'а оказалось несколько компаний, среди них «DeeProSoft» отвечает за программную составляющую проекта. Первое, что потребовалось для реализации проекта это - современный графический игровой движок, разработка которого и является предметом дипломирования. В своем дипломном проекте я затрону проектирование движка в целом и остановлюсь подробнее на проектирование и разработке ядра системы.
Глава 1
Игровой Движок -- это центральный программный компонент компьютерных и видео игр или других интерактивных приложений с графикой, обрабатываемой в реальном времени[11]. Он обеспечивает основные технологии, упрощает разработку и часто даёт игре возможность запускаться на нескольких платформах, таких как игровые консоли и настольные операционные системы, например, Linux, Mac OS X и Microsoft Windows. Основную функциональность обычно обеспечивает игровой движок, включающий движок рендеринга («визуализатор») для 2D или 3D графики, физический движок или обнаружение столкновений (и реакцию на столкновение), звук, скриптинг(система скриптования), анимацию, искусственный интеллект, сетевую поддержку, работу с потоками, управление памятью и граф сцены. Часто на процессе разработки можно сэкономить за счет повторного использования одного игрового движка для создания множества различных игр.
Так как планируется использовать разработанные технологии в дальнейшем, то важно, что бы основной код игры можно было неоднократно вторично использовать, в связи с этим и возникла необходимость в использование движка. Еще одним плюсом такого подхода является то, что разработку движка и игры можно вести практически независимо.
1.2 Требование к движку
В настоящее время представлено довольно много как коммерческих, так и свободных (Свободное программное обеспечение -- программное обеспечение, в отношении которого пользователь обладает «четырьмя свободами»: запускать, изучать, распространять и улучшать программу бесплатно.) игровых движков.
Нами планируется портировать (перенести) на новую технологию несколько старых проектов среди которых есть трехмерная Гео Информационная Система, по этому гибкость движка и его способность работать с большими объемами данных является принципиальным фактором.
Проекту был необходим современный движок соответствующий следующим основным критериям:
· Быстрый и актуальный
· Поддерживающий несколько систем рендеринга (OpenGL и DirectX)
· Расширяемый
· С открытым исходным кодом
· Поддерживающий несколько платформ (конкретно нас интересовала возможность работы с приставками)
· Экспорт трехмерных моделей из пакета трехмерного моделирования 3D Studio Max
· Работа со скриптами
(Скримптовый язымк (англ. scripting language, в русскоязычной литературе принято название язык сценариев) -- язык программирования, разработанный для записи «сценариев», последовательностей операций, которые пользователь может выполнять на компьютере. Простые скриптовые языки раньше часто называли языками пакетной обработки (batch languages или job control languages). Сценарии обычно интерпретируются, а не компилируются.
В прикладной программе, сценарий (скрипт) -- это программа, которая автоматизирует некоторую задачу, которую без сценария пользователь делал бы вручную, используя интерфейс программы.)
· Возможность разработки игры на C#
· Простая и гибкая ООП модель.
(Объемктно-ориентимрованное программимрование (ООП) -- парадигма программирования, в которой основными концепциями являются понятия объектов и классов (либо, в менее известном варианте языков с прототипированием -- прототипов).
Класс -- это тип, описывающий устройство объектов -- экземпляров. Класс можно сравнить с чертежом, согласно которому создаются объекты. Обычно классы разрабатывают таким образом, чтобы их объекты соответствовали объектам предметной области.)
1.3 Анализ существующих готовых решений (движков)
Среди коммерческих движков представлено довольно много готовых решений удовлетворяющих вышеуказанным требованиям. Среди них первыми приходят на ум такие монстры игровой индустрии как «Epic» с их движком «Unreal Engine».
Unreal Engine - игровой движок, разрабатываемый Epic Games. Первая игра, созданная на этом движке -- Unreal -- появилась в 1998 году. С тех пор различные версии Unreal Engine были использованы в десятках игр, в том числе Deus Ex, Lineage II, Thief: Deadly Shadows, сериях игр Brothers in Arms, Tom Clancy's Splinter Cell, Tom Clancy's Rainbow Six и, конечно, в серии игр Unreal. Будучи приспособленным в первую очередь для шутеров от первого лица, движок использовался и при создании игр других жанров.
Написанный на языке C++, движок подходит для создания игр для большинства популярных платформ: Win32, Linux, Mac OS X, консолей Xbox, Xbox 360, PlayStation 2, PlayStation Portable, PlayStation 3 и других. Для большей портируемости, движок поддерживает различные системы рендеринга (DirectX, OpenGL) и воспроизведения звука. Последняя версия - Unreal Engine 4, которая, несмотря на цену почти в миллион долларов, является одним из самых популярных движков.
Еще один наиболее современный и актуальный движок это - «Cry Engine 2».
CryEngine 2 -- игровой движок, созданный компанией Crytek и впервые используемый в шутере от первого лица Crysis. CryEngine 2 базируется на движке CryEngine, созданным этой же компанией в 2004 году и впервые используемым в игре Far Cry. На момент своего выхода является самым технологически продвинутым и фотореалистичным движком по сравнению с конкурентами. Сама Crytek позиционировала CryEngine 2 как первый по-настоящему фотореалистичный движок. Как стало известно с официальных источников, в сиквеле Crysis 2, который ожидается в 2009 году, разработчики улучшат текстуры и скелетную анимацию.
Оба вышеуказанных движка обладают широким набором всевозможных редакторов и утилит позволяющих собирать игру по кирпичикам практически без необходимости программирования. Но, тем не менее при необходимости, все их исходные коды являются открыты для разработчиков которые лицензировали движок.
Пожалуй, идеально под наши потребности подходит первый движок, но его заоблачная стоимость никак не входит в бюджет проекта, впрочем стоимость второго движка не намного меньше.
По этому мы решили обратиться к отечественным разработкам, которые должны быть намного дружелюбнее по цене за лицензию чем движки от именитых вендоров. Среди отечественных движков удалось выделить только два продукта достойных внимания.
Первый это - «Unigine», движок близкий по своему функционалу к «Unreal Engine», но как оказалось он еще довольно сильно далек от финального релиза да и даже за не законченную его версию авторы просят 75 тысяч долларов, что является неоправданно много.
Второй движок это - «NeoAxis».
NeoAxis Engine - это игровой движок, спроектированный для создания игр в практически любых жанрах. Движок также предназначен для создания 3D систем и систем виртуальных реальностей.
Особенности
· Движок проектируется так, чтобы быть максимально удобным и расширяемым.
· Благодаря уникальной системе сущностей и системе логики, написание и интеграция игровой логики проста и прозрачна.
· Широкие возможности инструментария максимально упростят написание игровой логики и создание контента. К ним относятся расширяемые редактор ресурсов и редактор карт.
· В качестве основного языка программирования взят C# и платформа .NET. Это даёт большое удобство и высокую скорость разработки. Вы можете писать дополнительные компоненты на любом .NET поддерживаемом языке программирования.
Как говорят сами авторы: «Наша главная цель - сделать движок максимально удобным и простым!».
Технически надо сказать этот движок выглядит на порядок проще, чем рассмотренные выше, но и его стоимость является вполне адекватной примерно 500 долларов за версию для коммерческого использования, а вот стоимость версии с исходными кодами оказалась все таки довольно высокой - 10 тысяч долларов. А версия без исходных кодов предоставляет слишком ограниченные возможности и если вполне годится для этого конкретного проекта, то вот использование в других проектах окажется не слишком удобна. Так же разочаровало быстродействие движка, возможно это связано с жесткой привязке к .Net платформе.
Рассмотрим свободные движки.
Выше мы рассмотрели коммерческие движки, но среди них не нашлось подходящего для наших целей решения. Основным фактором из-за которого пришлось отказаться от использования коммерческих движков является их высокая стоимость, которая не вписывается в смету проекта.
По этому следующим логичным шагом было обратить свое внимание на множество свободных движков.
Огромное количество энтузиастов выкладывают и поддерживают свои разработки совершенно безвозмездно, хотя некоторые спонсируются крупными фирмами, тем не менее, все эти движки являются совершенно бесплатными и как правило все их исходные коды - открыты. По этому наибольшее внимание стоит уделить именно этой нише.
Среди свободных движков чрезвычайно много проектов мягко говоря далеких от профессионального уровня, и это понятно, ничуть не меньше заброшенных и совершенно неактуальных проектов, по этому из изобилия свободных движков получилось выделить лишь два проекта, которые в целом отражают состояние этой ниши программных решений.
Первый движок это довольно известный «Ogre3D», движок широко используется в различных игровых проектах средней руки. Качество картинки выдаваемое движком весьма приличное. Он является кроссплатформерным, с открытым исходным кодом и написан на С++. Но как оказалось он представляет собой лишь систему рендеринга (отрисовки графики) и не имеет никакого инструментария, по этому он является графическим, но не игровым движком. По этому использовать его значит намертво привязать к конкретному проекту, что в дальнейшем не позволит разделить проект на две составляющие (движок и приложение). Выходом здесь может быть разработка своего движка на основе графического движка «Ogre3D», но это приведет либо к адаптации архитектуры разрабатываемого игрового движка под архитектуру графического движка, либо к тотальной переработке исходных кодов графического движка.
Следующий рассматриваемый движок это - «Irrlicht». Это полноценный игровой движок со всей присущей атрибутикой, такой как редакторы и четкая ООП модель, но вот бесполезным его делает техническая отсталость, картинка по качеству - 6 или даже 7 летней давности в лучшем случае, тем более упор в движке сделан на поддержку наибольшего числа языков программирования, по этому техническая база обновляется очень вяло. В результате некий анахронизм и недостаточное быстродействие не позволяют использовать его в современном проекте.
В результате про свободные движки можно сказать, что это либо хорошие системы рендеринга, либо устаревшие и вяло поддерживаемые технологии. Но тем не менее благодаря их открытому коду никто не запрещает заимствовать какие либо решения.
Тем самым рассмотрев представленные готовые как игровые, так и графические движки мы пришли к выводу, что разумным будет начать разработку своего движка изначально нацелив его на конкретные наши потребности, а в дальнейшим реализовать его архитектуру таким образом, что бы его легко можно было поддерживать актуальным и адаптировать под проекты любого рода которым необходима мощная 3D визуализация в реальном времени. Естественно для облегчения разработки мы планируем использовать фрагменты исходных кодов уже готовых движков. Например, в Ogre'е есть много хороших решений с 3D графикой, а у Irrlicht'а нам очень понравилась простая и четкая объектная модель.
1.4 Постановка задачи
Требуется разработать независимую технологическую основу для быстрой разработки на базе нее пользовательских приложений трехмерной визуализации в реальном времени. Иными словами, как было определено выше движок.
Конечный продукт должен обладать следующими качествами:
· Легкая расширяемость без необходимости пересборки всех исходных кодов
· Гибкость, возможность использования в различных разноплановых проектах
· Поддержка современных графических технологий
· Кроссплатформерность
· Несколько уровней абстракции
· Четкая ООП модель
· Поддержка нескольких языков программирования (C++, C# и Delphi)
· Стабильность в работе
Глава 2
В предыдущей главе мы определили требования которым должен отвечать конечный продукт. Эта глава будет посвящена собственно его проектированию и разработке.
Проект получил название «DeeProEngine» и далее будет фигурировать в тексте под аббревиатурой DPE.
В разработке DPE принимает участие несколько человек, где каждый отвечает за свой спектр задач. Моя роль в этом проекте заключалась в проектировании системы в целом и в разработке ядра системы. Остальные разработчики - писали модули и подсистемы подключаемые к ядру.
Также важно заметить, что целью диплома не является разработка движка в целом, она рассчитана на достаточно длительный период времени, предметом дипломирования является ядро системы, которое представляет собой независимый модуль физически выделенный в отдельную Dynamic-link library (динамически подключаемая библиотека далее DLL).
2.1 Проектирование архитектуры всей системы
Определившись с типом архитектуры можно перейти непосредственно к ее проектированию. Далее я не буду рассматривать движок как игровой т.к. между научной визуализацией и игровой грань очень размыта и по большому счету ее попросту нет.
Для того чтобы спроектировать по-настоящему гибкую и масштабируемую систему игры, необходимо не только понимать специфику игровых приложений, но и иметь представление об архитектуре программного обеспечения в общем. Книга Software Architecture in Practice, написанная Леном Бассом, Полем Клементсом и Риком Казманом (Len Bass, Paul Clements, and Rick Kazman) представляет собой хорошее введение в тематику разработки архитектуры программного обеспечения. Кроме того, авторы объясняют само понятие архитектуры ПО, рассматривают основные концепции, общепринятые подходы к проектированию программ, эталонные модели и стандартные примеры архитектур. Книга описывает многочисленные критерии качества архитектуры и рассказывает о том, какие методы лучше применять и каких подходов придерживаться, чтобы придать архитектуре требуемые свойства. Книга будет полезна как при выборе архитектурной модели, так и при реализации выбранной архитектуры. Авторы создали обширный справочник, который позволит существенно сократить поиск и выбрать одну из эталонных архитектурных моделей в качестве основы построения вашей системы.
Другой книгой, подробно разбирающей задачи проектирования и их решения, является книга Чарльза Ричтера (Charles Richter) под названием Designing Flexible Object-Oriented Systems with UML. Автор рассматривает большое количество относительно простых технологий, позволяющих повышать гибкость архитектуры. В книге описано несколько способов увеличения согласованности и уменьшения количества взаимозависимостей в системе, рассматриваются преимущества и недостатки абстрагирования и конкретизации на уровне классов и дается сравнение таких методов проектирования как специализация и агрегация. Ричтер в деталях рассказывает о том, как анализировать гибкость динамических диаграмм (например, диаграмм процессов). Методы анализа, описываемые в книге Ритчера - лакмусовая бумажка, которая покажет, насколько гибка спроектированная мной архитектура. Автор предлагает эффективный и вместе с тем информативный метод оценки архитектуры в плане ее гибкости. И если проверить выбранную архитектуру по тесту Ритчера на стадии проектирования, то на стадии реализации становиться понятным, какие алгоритмы и методы необходимо применить, чтобы получить желаемый результат. В настоящее время архитектура проектируется и разрабатывается под конкретную игру. Разумеется, разработчики игр могут перенести часть архитектуры или какие-то проектные решения, созданные и спроектированные для одной игры, в другую, однако это возможно не всегда, хотя и является де-факто устоявшимся методом проектирования, результаты применения которого зависят от индивидуального опыта разработчика. Таким образом, до сих пор лишь опытным разработчикам удается достигать желаемых результатов, но при этом проект редко сдается в срок и еще реже удается спланировать сам процесс разработки[1].
Одной из проблем подобного метода создания архитектуры игрового приложения является то, что такие качественные критерии как гибкость и расширяемость редко учитываются при планировании и проектировании системы. Так, например, компании id software при создании новой игры приходилось переписывать практически весь код предыдущей. Что наглядно видно на примере использования архитектуры игры Quake 3[2] для создания Doom 3. Несмотря на то, что обе игры принадлежат к одному жанру FPS и во многом похожи. Фактически, их единственное отличие заключается в улучшенной графике. С тех пор как развитие игр фактически свелось к улучшению графики, основной причиной переделывания структуры одной игры при создании новой является то, что существующие модели и архитектурные шаблоны не поддаются расширению. Пример проблем, с которыми столкнулась id, безусловно не единичен.
Рис 1. Архитектура Роллингса и Морриса (Rollings and Morris)
Роллингс и Моррис (Rollings and Dave Morris), авторы Game Architecture and Design, дают обзор существующих архитектурных моделей игровых приложений и пытаются выделить, насколько это возможно, основные элементы игровой архитектуры (см. рис 1 выше). Игра, построенная по схеме компонентов, представленная на рисунке 1, будет работать, но я считаю, что подобная сеть взаимоотношений и многочисленные связи между компонентами, сильно ограничивают расширяемость системы и возможность ее повторного использования в других проектах. Удобная архитектура должна не только логически разделять систему на подсистемы, она также должна предусматривать легкую замену или модификацию любой подсистемы без перестраивания системы целиком.
Отчасти проблемы заключаются в том, что в основе практически каждой модели игры лежит принцип объектно-ориентированности и, следовательно, в каждой игре присутствует чрезмерное количество взаимосвязей между компонентами системы. Игры практически всегда имеют дело с объектами, живущими в виртуальном мире. Игровые объекты обладают собственным поведением, отрисовывают сами себя на экране, а иногда даже говорят сами. Такой подход кажется логичным и его распространение, по всей видимости, связано со всеобщим признанием объектно-ориентированной парадигмы. Однако ограниченность данного подхода проявляется, как только сложность и запутанность таких функций как отрисовка (rendering) и принятие решений (ИИ) начинает расти экспоненциально. В свою очередь данное усложнение приводит к громоздкости игровых объектов в частности и архитектуры вообще.
Переход к системам, построенным на COTS (COTS - component off the shelf, методология, предписывающая разработчикам использование сторонних компонентов(плагинов).), является первым шагом на пути масштабного изменения игр, принципов их разработки и планирования. Однако несмотря на то, что использование готовых компонентов способно улучшить качество игры и сократить время ее разработки, использование объектно-ориентированного подхода приведет к тому, что компоненты едва ли будут более полезны, чем обычные библиотеки функций, помогающие оперировать объектами. Игровые объекты все еще ответственны за обработку своих данных, а именно, за рендеринг, за искусственный интеллект, звук, физику и т.д. Одним словом, игры пытаются использовать преимущества COTS-компонентов и вместе с этим оперируют слишком большими и сложными игровыми объектами. А это в свою очередь приводит к тому, что при разработке объектов разработчики жестко привязаны к используемым COTS-компонентам (см. рис. 2).
Рис 2. Сочетание метода COTS-разработки и объектно-центрированной модели
Вдобавок объектно-ориентированный подход ограничивает возможность повторного использования, даже при применении технологии COTS-компонентов[3]. Код, описывающий объект, всегда остается наихудшим в смысле повторного использования, но при совмещении объектно-ориентированных и COTS-технологий этот код содержит в себе еще и вызовы функций различных специализированных компонентов. Таким образом, при переходе на новый проект разработчики часто вынуждены переписывать код вследствие подобного взаимодействия объекта и компонентов. Даже хорошо спланированная и разработанная иерархия классов не способна уменьшить риск переписывания кода из-за того, что объекты остаются жестко связанными с используемыми COTS-компонентами. Я полагаю, что существует архитектура, способная значительно сократить количество переписываемого кода, вследствие ликвидации жестких взаимосвязей.
Совмещения всех COTS-компонентов в игровом ядре и есть игровой каркас - движок.
2.2 Постановка задачи по проектированию архитектуры
игра программный движок
Спроектировать архитектуру программного обеспечения как достаточно расширяемую, чтобы соответствовать современным технологиям, так и достаточно гибкую, чтобы поддерживать различные типы игр и приложений. Подобная архитектура обеспечила бы надежный фундамент для дальнейшего развития и, возможно, стала бы началом стандартизации взаимодействия между компонентами, используемыми в игре. Удачная архитектура развивалась и расширялась бы вместе с увеличением сложности современных игр и при этом не ограничивала бы творческий подход разработчиков игр. Для того чтобы достичь этой высокой цели, итоговая архитектура должна отвечать следующим требованиям.
· Требования к архитектуре: Поддержка концепции COTS-компонентной разработки
Во-первых, архитектура должна иметь строгую логическую структуру. Необходимо таким образом разделить систему на логически независимые части, чтобы каждая из подсистем могла быть разработана и оттестирована независимо от других. Это требование согласовывается с требованиями к COTS-системам, и я буду придерживаться принципов COTS-концепции.
Для того чтобы проверить, отвечает ли полученная архитектура данному требованию, разработчик должен продемонстрировать, что компоненты системы были разработаны и оттестированы независимо. Эти компоненты должны легко интегрироваться в итоговом игровом приложении и не требовать для этого больших изменений игрового кода. В идеале разработанные компоненты должны соединяться также легко, как если бы мы соединяли их на логическом уровне.
· Требования к архитектуре: Сокрытие деталей реализации и доступность применения без знания предметной области (локализация предметных областей)
Архитектурное требование о сокрытии деталей реализации и доступности применения существует из-за различных возможностей, требуемых в различных играх. В современных играх требуется высококлассная графика, реалистичная физика, человекоподобный искусственный интеллект, звук кинематографического качества. Даже если игровой разработчик использует COTS-компоненты для создания всего этого в игре, он должен хорошо знать предметную область - для того, чтобы использовать конкретный компонент корректно. Общеизвестно, что игровой разработчик вынужден быть экспертом в различных технических областях вместо того, чтобы сфокусироваться на создании собственно геймплея.
Требуемый уровень знаний предметной области будет лишь возрастать с усложнением игровых технологий, поэтому необходимо попытаться разрешить эту проблему как можно скорее. В своей концепции я стараюсь не только выявить общее в интерфейсах компонентов, но и спроектировать архитектуру таким образом, чтобы минимизировать объем знаний, требуемых для использования компонента, знаний о его интерфейсе (о его Application Programming Interface (API)). Для того чтобы проверить, отвечает ли полученная архитектура данному требованию, разработчик должен продемонстрировать, что работа с API скрыта в самом компоненте. Игровой программист не должен ничего знать о внутреннем устройстве компонента и о деталях предметной области для того, чтобы встроить компонент в игру.
· Требования к архитектуре: Гибкость и модифицируемость
Гибкость - ключ к будущему игр. Из-за постоянно растущей стоимости разработки возможность комбинировать и изменять существующие компоненты критична в плане сдерживания цен. Предлагаемая архитектура не зависит ни от жанра игры, ни от технологий, воплощаемых в ней, что позволяет разработчикам создавать различные игры, используя различные технологии. Для того, чтобы эта архитектура прижилась в игровой индустрии, она должна быть достаточно гибка, чтобы любая игра смогла использовать ее.
Для того чтобы проверить, отвечает ли полученная архитектура данному требованию, достаточно продемонстрировать, что разные игры могут быть написаны на ее основе.
· Требования к архитектуре: Масштабируемость и эксплутационная надежность
Другими критическими требованиями к архитектуре, также вытекающими из проблемы быстрого роста стоимости разработки, являются масштабируемость и эксплутационная надежность. Успешные игры часто появляются заново с различными дополнениями и улучшенным качеством. Так, например, компания Blizzard последовательно выпускала три версии своей игры под названием Warcraft, от Warcraft до Warcraft 3. В последней версии были добавлены новые герои и красивая трехмерная графика, но основа во всех трех версиях оставалась очень похожей. Успешная архитектура должна легко позволять подобную эволюцию игры.
Для того чтобы проверить, отвечает ли полученная архитектура данному требованию, достаточно продемонстрировать, что архитектура с легкостью поддерживает новые или улучшенные технологии, а также позволяет легко добавлять новые функциональные схемы в игру. Например, с помощью новой архитектуры разработчики смогут перенести игру из двухмерного пространства в трехмерное, не испытывая при этом трудностей с переписыванием уже написанных частей игры.
· Производительность и другие качественные параметры не являются приоритетными
Может показаться странным, что я не считаю производительность ключевым, главным требованием при проектировании архитектуры программ, предметная область которых постоянно напоминает о высокой планке производительности. Причина в том, что производительность в действительности играет несравнимо меньшую роль в вопросах межкомпонентного взаимодействия, чем производительность самих компонентов и подсистем игры. Например, отрисовка 10 миллионов треугольников одного объекта гораздо сильнее влияет на производительность, чем единичное межкомпонентное воздействие на графическую систему, вызывающее эту отрисовку. Я не стану игнорировать производительность при разработке архитектуры, но требования, описанные выше, имеют более высокий приоритет и значимость.
Другие качественные параметры, такие как надежность или совместимость, также будут учитываться. Однако в данном исследовании рассматриваются лишь те качественные параметры, которые могут быть проверены в заданные временные рамки. Последующая работа может включать в себя использование методов анализа с целью выбора компромиссного решения. Вследствие данных намерений только те качественные параметры, которые я считаю самыми важными, принимаются в качестве требований.
2.3 Выбор подходящих архитектурных концепций
Изначально подходя к разработке подобной масштабной системы очень важно выбрать ее правильную стратегию развития, т.к. изначально неверный подход к архитектуре, который может проявиться лишь в середине разработки может потребовать многие месяцы на полную переработку всего ранее написанного кода. С чем, конечно, не хотелось бы сталкиваться.
Перед тем, как мы сможем спроектировать архитектуру, необходимо определиться с основными архитектурными моделями. В своей наипростейшей форме архитектурная модель представляет собой набор компонентов, условия их взаимодействия и ограничения их применения. Объединение нескольких широко известных архитектурных шаблонов поможет нам построить сложную архитектуру, решающую поставленные задачи.
Рассмотрим некоторые архитектурные концепции, применение которых поможет нам реализовать требуемые качества в конечной архитектуре.
· Многоуровневость (слоистость)
Многоуровневая архитектурная концепция описывает разделение функционала системы на иерархические уровни, каждый из которых обеспечивает работу вышестоящего уровня и является его потомком[4]. Метод слоев поддерживает возможность повторного использования, располагая код, специфичный для данного приложения, на более высоких уровнях (слоях), позволяя разработчикам заново использовать каркас, образованный нижними уровнями. А возможность повторного использования неразрывно связана с нашими требованиями к конечной архитектуре такими, как гибкость и модифицируемость.
· Данные управляют всем (data-centered)
По существу, управляемость данными - это концепция, требующая наличия централизованного хранилища данных при полной независимости (друг от друга) клиентов, выполняющих обработку информации из хранилища[7]. Реализация этой концепции предлагает простой способ объединения различных систем, вследствие того, что клиенты могут ничего не знать друг о друге, а хранилище данных может ничего не знать о клиентах.
· Независимые компоненты
Данная концепция определяется наличием независимых компонентов (в общем случае, процессов), взаимодействие которых осуществляется посредством системы сообщении. Для корректного взаимодействия через систему сообщений компоненты "подписываются" на получение той информации, которую они обрабатывают. Одним из интересных преимуществ концепции независимых компонентов является то, что необязательно все компоненты должны присутствовать в системе при ее загрузке на исполнение и работе. Особенность распределенной системы взаимодействия посредством сообщений состоит в необязательности существования "подписчиков" на "опубликованные" (т.е. рассылаемые) сообщения. Качественно спроектированная подобная система допускает добавление/удаление функций и компонентов в любое время.
· Потоковая архитектура
Примером концепции информационных потоков (потоков данных) может служить система водоснабжения, состоящая из труб и фильтров. Эта концепция стремится обеспечить высокую степень повторного использования и сравнительно простую реализацию масштабируемости и устойчивости. Основываясь на последовательной обработке данных, система информационных потоков проста для понимания и применения. Расширение (масштабирование и модификация, в общем случае) системы сводится к простому подключению к существующей сети новых и различных компонентов обработки данных. Возможность безболезненного изменения (добавления новой функциональности - новых "фич" и возможностей) за счет изменения последовательности этапов, так называемого, конвейера и самих этапов обработки данных чрезвычайно привлекательна.
· Система систем (SoS или System of Systems). Интегрируемость
По сути дела, проектировщики часто используют идеи концепции системы систем при интегрировании множества сложных и разнородных систем в одну, более общую суперсистему[8]. Подход SoS интересен тем, что он описывает построение систем в различных программах, реализующих представления различных предметных областей, т.е. как раз таких систем, как игры или приложения промышленного уровня. Графика, физика, ИИ и т.д. являются, вообще говоря, различными предметными областями, но в случае игр они объединяются и используются совместно в одном приложении. Кроме того, систему, на концептуальном уровне SoS, представляют как множество, объединение подсистем (компонентов или в терминологии SoS, определений ("Definition")). Другими словами, игра - это объединение таких компонентов, как системы ИИ, системы физики, системы отображения и т.д.
Подобная точка зрения на вопросы архитектуры игры будет весьма полезна нам, ведь она удовлетворяет нашему изначальному требованию о сокрытии деталей реализации и доступности применения без знания предметной области. Это действительно становится возможным, если считать (и реализовать соотв.) графический "движок" законченной системой, и определить игру, как результат его взаимодействия с остальными системами.
Теперь перейдем с логического уровня на физический и рассмотрим как эти компоненты буду располагаться рамках проекта.
При проектировании такого рода систем рассматривается как правило несколько вариантов, если отбросить все которые явно по тем или иным причинам не подходят для игровых.
Первым глобальным и определяющим решением является то, каким образом движок обособлен от самого приложения его использующего. Тут возможно три основных варианты и их производные.
Первый вариант это когда движок просто представляет собой набор файлов с исходными и заголовочные файлы, которые содержат описание интерфейса движка доступного пользователю, через которые он и будет взаимодействовать с движком.
Такой подход наиболее распространен среди новичков, так как он наиболее простой в реализации и в принципе можно даже особо не задумываться об уровнях абстракции, при таком решении пользователь имеет доступ к любому месту в движке и может его изменять по своему усмотрению. В результате минусами такого подхода является то, что есть соблазн что либо изменить напрямую в коде движка и он плотно врастает в приложение его использующее, что в дальнейшем может привести к тому, что движок и само приложение с интегрированным нужно будет развивать как отдельные проекты. Следующим минусом является отсутствие ограничений по уровню доступа, т.е. разработчик приложения может менять любой фрагмент кода в движке, а если подобные изменения вносятся человеком с невысокой квалификацией, то это может привести как минимум к нестабильной работе всей системы. В принципе эти проблемы можно частично решить административными механизмами управления в команде разработчиков и хорошим проектированием, например, предоставить пользователю четкие интерфейсы, что бы у него не было необходимости просматривать сами исходные коды движка. К тому же у такого подхода есть еще и свои плюсы, основной это - простата проектирование, разработчикам движка в этом случае не приходится задумываться о межмодульном взаимодействии и отсюда же вытекает и следующее преимущество, это как раз отсутствие этого самого межмодульного взаимодействия, что положительно сказывается на быстродействие системы в целом.
Следующий вариант является некой модернизацией описанного выше архитектурного решения, это когда движок выделяется в отдельную библиотеку. В этом случае пользователь не имеет доступа к исходным кодам движка и работает лишь с вынесенным в заголовочные файлы интерфейсами. При таком подходе частично решается проблема с уровнями абстракции, но решается довольно грубо, пользователь просто не имеет возможности редактировать функциональность движка. Очень важным недостатком такой системы является проблематичность ее расширения, особенно когда над проектом работает несколько программистов. Все разработчики движка вынуждены работать с одним кодом который может быть достаточно слабо логически разделен на подсистемы. Этот недостаток присущ и предыдущему варианту архитектуры, что может привести к тому, что все подсистемы переплетаются внутри в один плотно связанный клубок распутать который уже не представляет никакой возможности. Стоит отметить, что так же как и в предыдущем варианте в этом - отсутствует межмодульное взаимодействие, что как уже говорилось выше положительно сказывается на быстродействии.
Третий вариант на мой взгляд наиболее интересен. Этот подход заключается в плагинной архитектуре. Плагин (от англ. plug-in) -- независимо компилируемый программный модуль, динамически подключаемый к основной программе, предназначенный для расширения и/или использования её возможностей[11]. Также может переводиться как «модуль». Плагины обычно выполняются в виде разделяемых библиотек. Принцип такой архитектуры заключается в том, что каждая подсистема выделена в отдельный независимый плагин, который имеет свой постоянный интерфейс. Эти плагины подключаются к ядру, которое занимается их менеджментом. Далее пользователь из ядра получает набор интерфейсов реализуемых в плагинах, с которыми ему и предстоит работать. Плюсы такой архитектуры заключаются в том, что все плагины могут разрабатываться независимо и любая подсистема может быть реализована несколькими принципиально разными плагинами. Например, система рендеринга может быть реализована двумя плагинами, один будет использовать Direct3D, а другой - OpenGL. А приложению использующему движок будет без разницы какой плагин в данный момент подключен и через что реализуется тот или иной функционал, т.к. это остается на более низком уровне абстракции. Такой подход может быть реализован для любой подсистемы движка. Неизменным остается лишь ядро. Но у этого подхода тоже есть свои минусы, основной из них это трудоемкость проектирования, оно заключается в том, что чтобы вся система работала как надо и плагинная архитектура могла проявить все свои достоинства все подсистемы должны практически изначально иметь четкие продуманные интерфейсы, которые будут реализовывать плагины. На определенном этапе вносить серьезные изменения в ключевые интерфейсы может оказаться весьма трудоемким и повлечь переработку многих плагинов. При грамотном проектировании основных интерфейсов должно быть как можно меньше, остальные же подвергаются изменениям без какого либо ущерба. Также при плагинной архитектуре стоит опасаться такого эффекта как «DLL Hell». «DLL hell» (DLL-кошмар, буквально: DLL-ад) -- тупиковая ситуация, связанная с управлением динамическими библиотеками DLL в операционной системе Microsoft Windows[11]. Сущность проблемы заключается в конфликте версий DLL, призванных поддерживать определённые функции. DLL hell -- пример плохой концепции программирования, которая, подобно скрытой мине, приводит к резкому возрастанию трудностей при усложнении и совершенствовании системы. Поэтому эксперты рекомендуют избегать или ограничивать применение DLL, обуславливающих такого рода конфликты. Для того, что бы этого не произошло надо изначально четко определить набор плагинов. По большому счета оба указанных выше недостатка решаются правильным проектированием и минусами как таковыми не являются, а вот следующий фактор действительно более значим. Плагины взаимодействуют друг с другом и с ядром по средствам интерфейсов (о выборе технологии будет написано ниже) и скорость этого взаимодействия на порядок ниже, чем к примеру когда все взаимодействие заключено в рамках одного приложения. Правда относительно мощностей современных компьютеров эти задержки ничтожно малы, но тем не менее факт остается фактом. В результате рассмотрев основные архитектуры движков, логичным выбором стала плагинная архитектура. Она наиболее подходит для проекта, т.к. соответствует принципам COTS и на ней проще всего будет реализовать все те требования, которые были заявлены выше.
2.4 Определение принципов межмодульного взаимодействия
Как было описано в пункте 2.1.3 архитектура движка должна вобрать в себя лучшее из уже сформировавшихся архитектурных решений, так же выше было определено, что основной парадигмой архитектуры будет ее плагинность и соответствие COTS принципам.
Так вся архитектура строится на межмодульном взаимодействии я считаю что начать проектирование стоит с определения того, как это межмодульное взаимодействие будет осуществляется.
Самый просто способ это просто передача между модулями указателя на экземпляр класса или интерфейс. Но нам нужно так же помнить о том, что движок должен работать с несколькими языками программирования и хранение структуры класса в памяти для каждого языка свое, по этому передавать указатель на класс попросту не получится, приведет к ошибкам. Для подобных случаев компания Microsoft предоставляет готовое решение Component Object Model (COM).
Принцип работы архитектуры COM в двух словах можно объяснить следующим образом.
Код классов располагается в библиотеках (DLL), которые регистрируются в специальном разделе системного реестра. Каждый класс реализует один или несколько известных COM-интерфейсов. DLL экспортирует функцию для создания экземпляра указанного класса, которая возвращает указатель на базовый интерфейс IUnknown (все классы обязаны реализовывать этот интерфейс).
Каждому интерфейсу (описанию интерфейса) сопоставляется уникальный идентификатор (Global unique identifier - GUID).
Для создания экземпляра класса пользователь вызывает функцию CoCreateInstance(GUID) из библиотеки COM. Именно она занимается просмотром записей в реестре, загрузкой DLL и вызовом функции создания экземпляра.
Пользователь работает с объектом через указатель на интерфейс.
Для контроля существования объекта используется подсчет ссылок. После использования экземпляра класса, пользователь обязан вызвать IUnknown->Release() для уничтожения объекта.
Архитектура COM предполагает независимость от компиляторов, и поэтому бинарный формат COM-интерфейсов строго регламентирован[9].
COM-интерфейс можно воспринимать как базовый абстрактный класс - без конструктора, деструктора и полей данных. На самом деле, именно так он и описывается в C++.
Указатель на COM объект можно воспринимать как указатель на экземпляр класса, который наследован от базового абстрактного класса.
В бинарном виде указатель на COM объект представляет собой указатель на экземпляр объекта, в первых четырех байтах которого содержится указатель на таблицу виртуальных функций (vtable).
Для реализации архитектуры движка было решено использовать упрощенную COM модель, т.е. обмен интерфейсами осуществлялся между модулями системы, без их регистрации в системном реестре, что позволит в дальнейшем сделать эту архитектуру кроссплатформерной т.к. практически полные аналоги COM есть и в NIX'овых системах и приставках (по крайней мере XBox 360).
2.5 Проектирование архитектуры
В этом разделе я займусь описанием непосредственно спроектированной мною архитектуры движка.
В общий принцип архитектуры движка заложен так называемый «принцип микроядра». Подобный принцип получил широкое распространение в операционных системах. Классические микроядра предоставляют лишь очень небольшой набор низкоуровневых примитивов, или системных вызовов, реализующих базовые сервисы операционной системы. Я постарался перенести этот принцип на архитектуру движка. И сделать так, что ядро реализует лишь минимальный общий для всех подсистем функционал и занимается управлением модулями, осуществляет межмодульное взаимодействие. Такой подход обеспечивает с одной стороны простоту разработки ядра, а с другой делает архитектуру системы в целом более прозрачной, еще немаловажным достоинством подобного подхода является то, что зависание или ошибки какого либо модуля системы не приводят к зависанию всей системы в целом. Конечно ошибки в самом ядре же наоборот делают систему неработоспособной, по этому очень важно сделать ядро максимально стабильным и работоспособным.
Следующим шагом я разбил все технологии и решения, которые планируется заложить в базовую архитектуру движка по модулям и записал их в текстовом виде.
· Ядро
o Система журналирования
o Сбор сведений об аппаратной составляющей ПК
o Отладочная консоль
o Базовая имплементация скриптовой системы
o Система событий (сообщений)
§ Главная система событий
§ Менеджер подключаемых из модулей систем событий
o Пространство рендеринга
§ Обработчик WinApi окна для Windows
§ Установка WinApi хуков для возможности рендеринга в «чужое» окно или компанент.
o Система управления подключаемыми модулями (плагинами)
o Базовая файловая система
· Файловая система (FS) (Plugin)
o Хранение файлов в паках (виртуальная файловая система)
o Загрузчик текстур
o Загрузчик шрифтов
o Загрузчик моделей
§ Статичные модели
§ Анимированные модели
o Загрузчик звуков и музыки
o Загрузчик материалов
o Универсальный загрузчик (возвращает указатель на файл)
o Plugin Пользовательские форматы паков с данными
o Plugin Пользоаптельские форматы текстур, шрифтов, моделей и т.д.
· Игровые сцены (Plugin)
o Статичные объекты
o Динамические объекты
o Ландшафт
o Поддержка BSP и OCtree
o Работа с камерами
o Статичное освещение
o Динамичное освещение
o Определение столкновений
o Система анализа видимости
o Физический движок
o 2D спрайтовый движок
o Менеджер системы частиц
o Графический пользовательский интерфейс
§ Plugin Пользовательские компоненты интерфейса
o Подсистемы менеджмента ресурсов
§ Менеджер текстур
§ Менеджер моделей
§ Менеджер звуков
§ Менеджер материалов
§ Plugin Пользовательский менеджер на базе основного
o Plugin Пользовательские объекты сцены
· Система менеджмента ввода (Plugin)
o Обработка мыши
o Обработка клавиатуры
o Обработка джойстика
· Система визуализации (графическая подсистема) (Plugin)
o 2D подсистема визуализации
§ Примитивы
§ Рендеринг текстур
§ Возможность совмещения 2D и 3D графики т.е. использование 3D моделей в двухмерной системе координат
§ Graphical User Interface (GUI)
o Алгоритм уменьшения количества полигонов модели (Mesh LOD)
o Отсечение по фрустуму
o High Dinamic Range(HDR) освещение
o Отражения
o Graphical Processor Unit(GPU) программы
o Рендеринг в текстуру
o Рельефное текстурирование по технике normal mapping
o Рельефное текстурирование по технике parallax mapping
o Небо
o Система рендеринга замкнутых помещений
§ BSP деревья
§ Статичные тени Lightmaps
§ Динамичные тени Shadow volumes
§ Оптимизация с использованием порталов
o Рендеринг открытых пространств
§ Octree
§ Ландшафты (карты высот)
§ Динамические тени по технологии hardware shadow mapping
· Звуковая система (Plugin)
o Поддержка звуковых файлов формата OGG
o Поддержка звуковых файлов формата WAV
В резултате такого разбиения я систематизировал все планируемые «фичи». Определился с основными подсистемами движка и функционалом который они должны реализовывать. Так же я определил подсистемы которые тоже в свою очередь могу расширятся за счет сторонних плагинов. Теперь можно перейти к составлению схемы движка в целом. Понятно, что центральным элементом системы выступает ядро, все остальные системы, как уже неоднократно писалось выше подключаются к ядру. Пользователь же находясь на самом верхнем уровне абстракции общается только с интерфейсами предоставляемыми ядром, у него так же сохраняется возможность запросить интерфейс любой подсистемы и работать с ней напрямую, но об уровнях абстракции я напишу чуть ниже. В результате я спроектировал систему удовлетворяющую всем вышеупомянутым требования. Сама схема представлена на рисунке 3.
Рис. 3 Упрощенная схема архитектуры движка DPE
Из схемы видно, как подключаются и взаимодействуют между собой модули и какие интерфейсы каждый из них реализует. Несколькими словами описать систему можно так, что ядро просматривает доступные для подключения модули (оно может искать их автоматически в заданных папках или же они могут быть жестко прописаны пользователем), из заголовка модуля оно узнает какую именно подсистему он реализует и подключает его к себе. В момент подключения модуль создает свой основной класс и передает ядру указатель на его интерфейс. Через этот основной класс модуль может реализовывать сколь угодно много дополнительных классов интерфейсы которые будут доступны через базовый класс модуля. Также в ядре регистрируются системы событий модулей, что позволяет обмениваться модулям сообщениями и подписываться на рассылки определенных сообщений, при этом сами подключаемые модули могут ничего не знать друг о друге. Так же каждый подключаемый модуль получает указатель на базовый интерфейс ядра, который предоставляет модулю доступ к некоторым возможностям ядра, например, к системному журналу. Через интерфейс предоставляемый ядром подключаемым модулям любой из них может напрямую обратиться к интерфейсу любого другого модуля. Пользователь из ядра получает в свое распоряжение свой экземпляр базового интерфейса ядра, через который он так же может работать с самим ядром и получать пользовательские интерфейсы плагинов.
2.6 Уровни абстракции архитектуры движка
В движке есть четко разграниченные уровни абстракции, которые по принципу слоенного пирога логически разделяют программирование для разных уровней движка. Выше уже писалось, что такое разделение необходимо, во-первых, что бы была четкая логическая структура движка в целом, во-вторых, что бы пользователь не мог получить прямой доступ к любому места движка (фактически доступ он конечно имеет, но что бы пойти и переправить что - либо в рендере например это уже должен быть обдуманный шаг и скорее всего пользователь постарается изначально решить эту проблему на более высоком уровне абстракции), в-третьих, это разграничение полезно самим разработчикам движка.
Движок все-таки накладывает определенные ограничения на пользователя, к примеру, опуститься до уровня GAPI(интерфейсов DirectX или OpenGL) ему никто не даст. Идеология движка заключается в том, что пользователь не получает исходные коды движка, в его распоряжении оказывается лишь набор интерфейсов, сам движок - набор библиотек и документация к интерфейсам. По этому изначально пользователю доступно лишь несколько верхних уровней абстракции, о которых я напишу чуть ниже.
Программирование на каждом из уровней абстракции осуществляется на одном или нескольких пригодных для этого уровня языках программирования. На самом верхнем уровне это скриптовый интерпретируемый движком язык, а на нижнем это может быть только C++. Схема приведена на рисунке 4 на следующей странице.
Пользователь получает доступ к следующим уровням.
Самый верхний, как это уже было написано выше это скриптовый язык. Он представляет собой небольшой набор классов с основным функционалом и не позволяет с этого уровня этот функционал изменять, тем не менее, на этом уровне без проблем можно польностью реализовать несложное приложение. Основным плюсом работы на этом уровне является то, что пользователь работает с интерпретируемым языком со всеми его плюсами, а следовательно разработка кода наиболее проста и эффективна.
Подобные документы
Разработка компьютерной игры "Эволюция" с помощью игрового движка Unit. Сравнение критериев игры-аналога и разрабатываемой игры. Разработка графического интерфейса пользователя. Настройки камеры в редакторе Unity. Структура файла сохранения игры.
дипломная работа [3,6 M], добавлен 11.02.2017Игровой движок Unity, его использование для создания приложений, связанных с архитектурой, обучением, визуализацией данных и электронными книгами. Разработка системы освещения для работы с двухмерными объектами в виде расширения редактора Unity.
дипломная работа [2,5 M], добавлен 11.02.2017Разработка игрового "движка" с использованием языка C++ для написания кода, графического пакета DirectX9 для вывода графики. Использование физического "движка" PhysX для взаимодействия объектов. Технико-математическое описание задачи, листинг программы.
дипломная работа [4,5 M], добавлен 02.09.2013Язык программирования Pascal и его турбооболочка. Аналитический обзор игрового программного обеспечения. Функции модуля Crt. Постановка задачи создания несложной игровой программы "Турбозмей", алгоритм реализации и описание пользовательского интерфейса.
курсовая работа [100,4 K], добавлен 15.05.2014Понятие и эволюция игр, анализ их различных жанров и существующих аналогов. Выбор программных средств для реализации игры, написание сюжета и выбор среды разработки игры. Алгоритмы для придания гибкости обучающей игре. Описание программных модулей.
дипломная работа [2,7 M], добавлен 27.10.2017Знакомство с основными особенностями развития игровой индустрии. Создание компьютерных игр как одна из прикладных сфер программирования. Общая характеристика набора методов класса Area. Рассмотрение способов создания игры "Змейка", анализ этапов.
курсовая работа [799,4 K], добавлен 13.06.2013Разработка технической демонстрационной версии трехмерной компьютерной ролевой игры "After Reset". Установка, запуск и минимальные требования программы. Анализ алгоритмов. Архитектура системы и иерархия классов. Тестирование программного обеспечения.
дипломная работа [3,4 M], добавлен 19.07.2014Разработка программного продукта, предназначенного для имитации физического взаимодействия между объектами на основе игрового симулятора. Проектирование программы "LonelySpaceRanger", код которой представлен на языке VisualС++. Разработка интерфейса.
дипломная работа [3,2 M], добавлен 30.11.2011Анализ деятельности группы компаний "Инрэко ЛАН". Общая характеристика, основы проектирования и разработка операционной системы Android. Этапы разработки программного игрового приложения с использованием физики. Скриншоты, отображающие игровой процесс.
отчет по практике [2,7 M], добавлен 19.07.2012История создания компьютерных игр. Обзор современных игровых жанров. Выбор используемых инструментов. Руководство пользователя. Разработка игры в жанре 3D шутера от первого лица. Конструктор игр Game Maker. Создание уровня с несколькими регионами.
курсовая работа [961,8 K], добавлен 22.06.2015