ВВЕДЕНИЕ
Темой данной проектной работы является создание игрового движка на языке программирования C++. Игровые движки — это базовое программное обеспечение для большинства компьютерных игр.
Мы выбрали эту тему потому, что нам интересна разработка игр и нам было интересно узнать, как работают игровые движки в недрах.
Целью проектной работы является создание игрового движка, способного выполнять все базовые потребности для ascii-игр. ASCII (англ.American Standard Code for Information Interchange) — американская стандартная кодировочная таблица для печатных символов и некоторых специальных кодов.
Задачами данной работы являются:
- в теоретической части работы рассказать, что такое игровые движки и принцип их работы;
- создать наш работающий ascii-движок, объём занимаемой памяти которого будет менее 5Мб;
- сделать пример игры на своем ascii-движке.
ТЕОРЕТИЧЕСКАЯ ЧАСТЬ
Что такое игровой движок
Игровой движок (англ. game engine) — это базовое программное обеспечение игры, которое пригодно для повторного использования и расширения, и тем самым может быть рассмотрено как основание для разработки множества различных игр без существенных изменений.
Термин «игровой движок» появился в середине 1990-х в контексте компьютерных игр жанра «шутер от первого лица» похожих на популярную в то время Doom. Архитектура программного обеспечения Doom была построена таким образом, что представляла собой разумное и хорошо выполненное разделение центральных компонентов игры (например, подсистемы трёхмерной графики, расчета столкновений обьектов, звуковой и других) и графических ресурсов, игровых миров, формирующие опыт игрока, игровые правила и другое. Как следствие, это получило определённую ценность за счёт того, что начали создаваться игры с минимальными изменениями, когда при наличии игрового движка компании создавали новую графику, оружие, персонажей, правила игры и тому подобное.
Разделение между игрой и игровым движком
Разделение между игрой и игровым движком часто неопределённое. Некоторые движки имеют разумное и ясное разделение, в то же время другие практически невозможно отделить от игры. Например, в игре движок может «знать» о том, как рисовать дугу, в то же время другой движок может работать с другим уровнем абстракции, и в нём дуга будет частным случаем параметров вызываемых функций. Одним из признаков игрового движка является применение архитектуры управления данными. Это определяется тем, что если игра содержит жёстко фиксированные данные, влияющие на логику, правила игры, рисование объектов и тому подобное, то становится сложно применять данное программное обеспечение в разных играx.
Большинство игровых движков разработано и настроено для того, чтобы запустить определённую игру на определённой платформе. И даже наиболее обобщённые многоплатформенные движки подходят для построения игр определённого жанра, например, шутеров первого лица или гонок. В данном контексте можно сказать, что игровой движок становится не оптимальным при его применении не для той игры или той платформы, для которой разработан.
Как они устроены
Сначала движки создавались как единое целое: рендеринг, физика, звук и тому подобное были все вместе. Однако такой подход приводит к сложностям при добавлении нового контента в игру, и-за чего новые игровые движки используют более свежий подход.
Новая система позволяет заменять или расширять некоторые системы движка компонентами, например, для физики, для звука, для рендеринга.
Некоторые игровые движки, такие как RenderWare, проектируются как набор слабосвязанных компонентов, которые могут выборочно комбинироваться для создания собственного движка, вместо более традиционного подхода расширения. Несмотря на специфичность названия, игровые движки часто используются в других типах интерактивных приложений, требующих графику в реальном времени, таких как рекламные демо-ролики, архитектурные визуализации, обучающие симуляторы и среды моделирования.
Также, некоторые игровые движки предоставляют только возможности 3D-рендеринга в реальном времени вместо всей функциональности, необходимой играм. Эти движки доверяют разработчику игры реализацию остальной функциональности или её сбор на основе других игровых ППО компонентов. Такие типы движков обычно относят к «графическим движкам». Некоторые примеры графических движков: RealmForge, Ogre 3D и Genesis3D.
ПРАКТИЧЕСКАЯ ЧАСТЬ
1. Из чего состоит наш движок
Наш ascii-движок разделен на несколько частей, помогающих сохранять в нём порядок и быструю возможность расширения. Я бы хотел рассказать о том, как он устроен и чем компилируется.
1.1. «Core» (ядро)
Первой частью движка является «core» (ядро), которое содержит необходимые для его работы составляющие:
- основной класс движка;
- класс шрифтов;
- базовый класс программы пользователя.
В основном файле движка содержатся функции создания окон, добавления сцен, рисования, получение данных операционной системы и ещё множество разных функций.
Класс шрифтов является оберткой над низкоуровневой структурой шрифта. В нём содержится функция загрузки новых шрифтов.
Базовый класс программы пользователя содержит шаблон функций, таких как отрисовка, обновление и обработка событий.
В библиотеках содержатся кэширование шрифтов и библиотека для работы с utf8 - Unicode.
1.2. «Client» (клиентская часть)
Второй частью движка является «client» (клиентская часть), в которой лежат все полезные классы для работы с текстом, шейдерами, пользовательским интерфейсом и анимациями. Рассмотрим их немного подробнее. Несколько классов нужны для анимированного текста, два из которых позволяют скреплять несколько кусков текста с разными задержками. Класс анимаций позволяет загружать анимированные данные, отрисовывать их разными способами, ставить задержку для анимаций.
1.3. «Additional» (дополнительная)
Третья часть движка называется «additional» (дополнительная), то есть в ней содержатся дополнительные части движка, которые можно заменять, добавлять и увеличивать функционал без вреда для самого движка. Весь раздел достаточно большой, и из-за этого был разделен на три части: «events» (события), «utils» (утилиты) и остальные дополнения. События в движке являются объединением шаблонов проектирования «observer» (наблюдатель) и «event queue» (цикл событий). Дополнительно используется паттерн «singleton» (одиночка).
Утилиты содержат в себе функции для быстрого получения данных из файлов, создания директорий и проверки их существования.
Остальными дополнениями являются: камера, которую, например, можно привязать к игроку, музыкальный движок, позволяющий проигрывать mp3 и ogg формат, базовый класс сцен и класс для сохранения данных в бинарный формат, необходимый для последующего быстрого считывания данных.
2. Сборка движка
Движок собирается и компилируется с помощью нашего автоматического сборщика проектов — «SPAM» (Simple Project auto-building tool for AsciiMachine). «SPAM» принимает на вход программу на языке программирования Lua и отдает на выход сборочный файл на Makefile. При создании сборочного файла можно выбрать некоторое количество опций. Обязательной опцией является выбор платформы. Поддерживается сборка Linux, Windows и web-версия (с использованием Emscripten).
3. Примеры
Для примера работоспособности моего движка мы сделали достаточно интересную и популярную игру в ascii — Flappy Bird. Реализация достаточно простая, поэтому для всей игры было использовано всего 2 текстуры самой «птички». На самом деле, труб всего 4 на всей карте, и они уничтожаются после выхода за границы экрана. В игре есть кнопки, звуки, анимации, переход сцен, события и немного математики.
ЗАКЛЮЧЕНИЕ
Мы считаем, что в результате работы все задачи, поставленные нами, были выполнены. В процессе написания теоретической части работы мы рассказали ио движках и о том как они работают. В практической же части игровой ascii-движок был создан, игра на нём была сделана и объём занимаемой памяти движка и игры меньше 5 мегабайт.
ЛИТЕРАТУРА
1. https://martalex.gitbooks.io/gameprogrammingpatterns/content/ - была использована для воссоздания некоторых шаблонов проектирования
2. https://habr.com/ - был использован для вдохновения.
3. https://en.cppreference.com/w/cpp/ - был использован для изучения стандартной библиотеки C++.