Мой опыт в написании игр
Здесь я расскажу о своем лучшем на данный момент проекте – игре, написанной после четвертого курса на WinAPI. На то время
в памяти всплывала старая добрая игра battle-city
, и я решил попробовать сделать похожую. По времени на это ушло около двух
месяцев, хотя большая часть там была не существенна, и сам движок был разработан значительно быстрее. По сути, единственной
средой, которой я владел к тому времени, была всего-то WinAPI, а ее показатели оставляют желать лучшего. Вследствие этого
я сразу решил позаботиться о графике вручную, к тому же у меня уже был большой разносторонний опыт в этом направлении, но
так как игра 2D и сделана полностью на текстурах, работа с графикой там, по сути, заканчивается на одной функции.
Графический движок.
Та основная функция, как сразу можно догадаться – функция вывода картинки поверх другой, в режимах копирования и альфа – перехода плюс зацикливание текстуры для фона и стен. В итоге был сделан класс 32-битной картинки, в котором делалось все, что нужно, а после готовая пиксельная матрица непосредственно выводилась в окно функцией SetDIBitsToDevice, результат был значительно приятнее всяких BitBlt – нет мерцания, синхронизированный вывод, да и побыстрее вроде-бы :). Сами текстуры были благополучно найдены в интернете и обработаны. С анимациями было уже посложнее, один взрыв был удачно извлечен и обработан из 2го «Крепкого Орешка» :), второй уже был чисто сгенерирован, хоть и криво но успешно в последовательности particle illusion/virtualdub/моя функция/virtualdub/sony vegas, еще несколько анимаций были сделаны в последнем. Все это в конце концов заняло целых 100 tga файлов, которые были склеены группами в целях удобства и чтобы не мучить файловую систему :). Функции для работы с Tga, кстати, тоже писались мной, т.к. не являются встроенными, хотя естественно в интернете их можно найти и это open-source.
Основной (физический движок).
В оригинальной игре стенки уничтожались кусками определенного размера, но мне такое не по душе и я сделал все векторным, то есть для задеваемой стены рассчитывалась область уничтожения и удалялась, преобразуя прямоугольный объект в 1-4 (реально в 1-3) новых. Я сделал специальный менеджер объектов, который по моим представлениям является основой любой игры со сложными взаимодействиями. Менеджер выделяет массив объектов и массив ссылок на них, при создании и освобождении объектов работа идет только со ссылками. В результате получены необходимые характеристики:
- обращение к объекту по индексу – очень быстро (три операции);
- выделение нового объекта – быстро (несколько операций, не зависимо от количества объектов);
- удаление объекта – медленно, в среднем прямо пропорционально количеству элементов (сдвиг части ссылок).
Интеллект соперников.
Самая сложная часть игры, я долго придумывал саму идею, оставляя при этом случайное поведение соперников. В итоге придумал векторный
алгоритм поиска игрока противником, сначала он был «безшансовый» то есть находил кратчайший путь куда угодно, если таковой был. Но это
было слишком и требовало немеряно вычислений, конечный вариант хорошо оптимизирован и «видит не дальше одного поворота». Идея рекурсивного
алгоритма заключается в пускании лучей во все стороны от текущей позиции соперника, разбивании их о преграды и смены направления с
вертикального на горизонтальное и наоборот. Новые лучи имеют ширину, равную длине породившего их луча. Выглядит это так:
Самую важную роль для быстродействия играют списки объектов, упорядоченные по соответствующим им координатам, т.к. каждый под-луч порождает рекурсивный вызов, если он достаточной ширины для прохода противника, разумно обрезать его по ближайшей преграде.
Представление текстур.
На каком-то этапе я решил что ~1.5 мегабайта на эту игру – это сильно много, а поскольку работать здесь с png было неудобно (громоздкая система вызовов функций в найденной библиотеке и невозможность паковать по многу картинок в один файл), так я решил попробовать написать свой кодек для изображений со сжатием без потери качества. Кодеку дал банальное название CIMG от Compressed Image (как позже оказалось, уже существует открытая библиотека с таким названием но другим назначением - что не удивительно). В итоге за довольно небольшое время я получил неплохой результат, и потом продолжал развитие этой идеи уже в отдельной библиотеке (на данный момент у меня четыре своих библиотеки: сжатия по Хаффману, скоростного сжатия по «моему методу» ориентированному на изображения, CIMG, библиотека графических функций). Вся сотня текстур игры в 32-битном цветовом формате (RGBA) с суммарным размером 0.357 мегапикселя упакована в 5 файлов с общим сжатием в 2.11 раза, что определенно сильный результат. Потестировав CIMG на различных файлах могу сказать, что он не так сильно жмет скриншоты десктопа и картинки с повторяющимися участками, как png, но в среднем не уступает ему. Например, я взял 10 высококачественных обычных фотографий разного плана с 24 бит цвета, уменьшил до 1296х972, это занимает столько места:
- TGA Uncompressed : 36.0 мб;
- TGA RLE : 34.4 мб;
- PNG : 18.3 мб;
- PNG Quick Compress : 18.1 мб (как не странно, меньше предыдущего :));
- CIMG : 17.5 мб.
В заключении возвращаюсь непосредственно к игре. Слова словами, а посмотреть и опробовать результат – совсем другое дело, поэтому ниже расположены скриншот и ссылка на архив с игрой. Меню отсутствует, здесь нет видимости завершенной игры рассчитанной на распространение, т.к. она такой и не является. Загрузка карты – файл *.sce (прилагается и конструктор карт :)) и вперед. Основное управление – стрелки, wasd, home, c, shift, pause, подробнее можно посмотреть по «F1».
По части программирования:
- 6 классов;
- суммарный размер кода на игру и конструктор карт (не включая сгенерированный - диалоги, id кнопок) – 101 кбайт (плюс пара функций графической библиотеки, библиотека cimg и соответственно пара библиотек сжатия – около 120 кбайт).
У меня были проблемы с форматами при создании текстур и видео, а именно - из основных форматов альфа канал поддерживают png и tga, рендерить файлы с ним я мог только в png,
свободного конвертора png32 -> tga32 в интернете я найти не смог и пришлось написать свой, с использованием открытой библиотеки PNGlib и хочу выложить его в свободное использование.
Скачать конвертор png32 bit -> tga32 bit (Win32)
Его возможности:
- входной формат только png32;
- выбор множества файлов;
- выходной формат tga32:
- без сжатия;
- RLE - сжатие;
- изменение размеров изображений (resampling) по всем четырем цветовым каналам на заданное (2..2048)х(2..2048) одной из двух фильтраций:
- билинейная (bilinear);
- анизотропная (anisotropic).