Как создавать игры стратегии
Перейти к содержимому

Как создавать игры стратегии

  • автор:

Повесть о создании классической RTS в домашних условиях с нуля + разбор основных этапов разработки (AI, сеть и т.д.)

image

В статье речь пойдет об одном очень не новом проекте, который создавался совсем в другое время и совсем в других условиях. Это моя старенькая RTS под названием Земля онимодов (Onimod land). Чтобы было сразу понятно, что она собой представляет, можно посмотреть коротенькое видео:

У этой статьи есть продолжение.

Пожалуй, будет правильным сразу же уточнить следующее: Данная игра была запрограммирована когда-то лично мною с нуля без движков, конструкторов и прочих современных инструментов. Проект достаточно большой и делался на чистом энтузиазме несколько лет. Вопреки всем законам экономики мне-таки удалось довести эту работу до конца, правда, к тому моменту численность команды разработчиков уже уменьшилась до одного человека. К сожалению, на момент своего выхода эта игра не могла по многим причинам оказаться востребованной широкими массами игроков — рынок игр поменялся сначала в сторону 3D, потом в сторону казуальных игр. Долгое время эта игра лежала у меня, так сказать, «на полке», да и сам я давно перестал быть разработчиком игр.

Тем не менее, вспомнить о том, как всё это делалось, мне достаточно интересно. Тем более, что лично я играю в собственную игру с большим удовольствием. Я совершенно не уверен, что всем известный Blizzard делал свой Starcraft по той же схеме, что и я, но я точно помню, что по ходу разработки я периодически натыкался на те же самые проблемы, на которые в своё время натыкались разработчики Blizzard-а. Это можно было понять по тем решениям, которые и им, и мне пришлось использовать, чтобы выпутаться из одинаковой «ситуации». Свой вариант о том, как я всё это делал, я и предлагаю вашему вниманию. В конце я коротко опишу сами условия, в которых происходила разработка, а также те «правила игры», которые на тот момент устанавливали российские издатели.

В статье делается попытка описать общее устройство классической RTS. Естественно, что описание будет не особенно подробным, так как нет никакой возможности описать подробно такой объем кода (да и, честно говоря, даже для автора удержать в голове тонкости реализации нереально, особенно учитывая, сколько уже лет минуло). Однако, хочется надеяться, что какое-то пусть и поверхностное представление о том, как всё это делается с нуля, мне осветить удастся. Кое-где я буду вставлять небольшие куски исходного кода, но делать это буду, скорее, для демонстрации принципа, чем для чего большего.

Будут рассмотрены следующие механизмы, которые, на мой взгляд, являются фундаментальными:

  • Графика (в каком виде, что и как).
  • Игровые ресурсы / редактор ресурсов — подготовка спрайтов для игры, создание игровых объектов (юнитов и зданий).
  • Управление объектами — сказ о том, как заставить юнитов что-то делать.
  • Алгоритм поиска пути.
  • AI или Искусственный интеллект — раздел сначала разбирает действия Инстинктов или врожденную сообразительность юнитов, а потом уже пытается пояснить процесс глобального управления командой.
  • Сеть.
  • Коротко об авторах и о проделанной работе.
  • Стартовые условия и их последствия — это лирический раздел, не имеющий отношения к сути статьи. Я решил, что он не будет лишним, так как наши представления о том времени могут быть различными. Поэтому я кратенько освещу свой вариант ситуации, в которой начинался этот проект.

RTS

В качестве игрового жанра была однозначно выбрана RTS с типом графики 2D в изометрии. Такой выбор был обоснован исключительно нашими личными предпочтениями. Основным языком программирования я выбрал для себя C++, который после длительного программирования на ассемблере на процессоре типа Z80 (ZX-Spectrum) показался мне очень простым, так как по своей сути сильно напоминал очень высокоуровневый ассемблер. Хотя должен признать, что я долго не мог привыкнуть использовать виртуальные функции, а без этого C++ сильно похож на обычный C.

На мой взгляд, если вы делаете игру с нуля, то первое, что нужно сделать — это получить хоть какое-то изображение на экране. Имеется в виду, конечно, что изображение должно быть осмысленным, т.е. своим появлением тестировать игровые механизмы. Основной момент здесь — это способ попадания графики в игру и её последующая отрисовка. Именно с этих двух моментов нужно всё начинать.

Графика

В тот момент подавляющее большинство игр использовало 8-битное цветовое разрешение, и мы логично решили, что мы пойдем дальше и наша игра будет использовать 16-битные цвета. Почему не 24-битные? На тот момент на видеокартах в качестве нормы присутствовал 1 Мб памяти. Количество памяти, которое потребуется под одну экранную поверхность 800×600, соответственно, составит 800 x 600 x 2 = 960000 байт или 937,5 КБайт. Т.е. под одну экранную поверхность задействовалась почти вся видеопамять тогдашних видеокарт. Изначально наша игра должна была уметь работать в режиме экрана 640×480, но в дальнейшем этот вопрос был пересмотрен в настоящий момент игра работает с любым разрешением, которое позволяет монитор.

Для хранения графики требуется память. Понятно, что хранить что-то на видеокарте в моем случае не получится, да это и невозможно с учетом предъявляемых требований. Поэтому спрайты должны лежать в ОЗУ.

К самому спрайту предъявлялись следующие требования:

image

  • Спрайт должен обладать именем.
  • Сжатый спрайт может иметь любую форму, а не только прямоугольную. Пиксели, которые на изначальной прямоугольной форме полностью прозрачны, обозначаются специальным цветом, чтобы их можно было отбросить.

image

  • Полупрозрачные пикселы не используются.
  • Спрайт может содержать идентификационный цвет, который можно менять во время рисования. Это требуется, чтобы «отмечать» юниты/здания, принадлежащие к одной команде, своим цветом.

image

  • Вместо 16-битного цвета закодированный спрайт должен содержать индекс цвета в палитре, который кодируется 1 байтом. Палитры будут строится отдельно для большого количества спрайтов. Такой подход позволял сильно экономить на хранении самого цвета, но требовал возможности переключать текущую палитру во время визуализации. Однако чаще всего спрайту вполне хватало одной палитры.
  • Спрайт должен содержать, так называемый, pivot (координату начала спрайта), относительно которой производится рисование.
  • Спрайт может обладать размерами в «клетках». Игровое поле — это клеточный мир, поэтому иногда полезно знать то пространство, которое занимает спрайт на игровом поле.

На картинке показаны размеры спрайтов в «клетках» и положение спрайта относительно клеток, т.е. pivot.

В результате по спрайтам я принял такое решение: хранить графику в памяти в сжатом виде и раскодировать её в момент вывода на экран. Главным плюсом этого варианта является малое количество памяти, которое требуется спрайт, главным минусом, естественно, будет постоянное раскодирование процессором каждого спрайта в момент рисования. Что для этого требуется? Нужен формат сжатия и алгоритм, который будет сжимать и разжимать картинку.

Для сжатия был выбран следующий способ. Алгоритм проходил по прямоугольной области спрайта по вертикали, начиная от левого верхнего угла. Основной для рисования служили вертикальные неразрывные полоски пикселей (вертикаль была выбрана из того простого соображения, что юниты в основном имеют больший размер по высоте). Каждая такая полоска запоминалась как массив, о котором известно количество пикселей и цвета этих пикселей. Когда полоска прерывалась «пустым» пикселем, то происходил поиск следующей вертикальной полоски. Между окончание одной полоски и началом следующей сохранялось смещение координат, что позволяло избежать хранения и, самое главное, рисования «пустых» пикселей. Ко всему этому добавлялись трюки с палитрами, которые могли переключаться на ходу. В упрощенном виде формат сжатия представлял из себя следующие команды:

  • Смещение координат относительно предыдущей порции пикселей
  • Массив цветов пикселей по вертикали (количество, затем цвета)
  • Установка новой палитры

В качестве дополнительной оптимизации был использован такой прием. Многие здания содержали анимацию, которая занимала куда больше места, чем занимал бы просто статический спрайт здания. Но так как само здание всегда отображалось статическим спрайтом, а анимация накладывалась поверх спрайта, то из анимации можно было выбросить те пиксели, которые по цвету совпадали с цветом статического спрайта здания. Обычно это удаляло большую часть пикселей из спрайта с анимацией.

Например, в игре Ферма выглядела так:

image

В реальности же графика хранилась так:

image

Теперь надо решить вопрос с раскодировкой сжатого изображения. А эта задача оказывается значительно сложнее, чем само сжатие. Принципиальное отличие состоит в том, что сжимать изображение можно заранее, т.е. не заботясь о скорости этого процесса. Раскодирование же должно выполняться «на лету» причем постоянно и для каждого спрайта, выводимого на экран. И именно в этом моменте и заключалась главная трудность. Вторая трудность, вытекающая из первой состояла в том, что спрайты должны раскодироваться разными способами. Например, представим, что какой-то юнит включил себе режим «маскировки», который визуально выглядит так, что он начинает быстро становиться прозрачным почти до полного растворения. Или, допустим, у летающих юнитов должна присутствовать тень на поверхности ландшафта, причем тень на деле являлась отдельным спрайтом, чтобы летающий юнит мог изменять высоту, а тень при этом оставалась на земле. Тень всегда черная и всегда обладает прозрачностью, а значит её можно раскодировать по собственному алгоритму.

image

image

Или еще один пример, направленный на оптимизацию — если заранее известно, что спрайт использует только одну палитру, то достаточно выставить её один раз и при раскодировании вообще не проверять на изменение палитры. В общем, вариантов по улучшению алгоритма раскодирования для частных случаев вполне хватает. Присутствовал даже такой экзотический вариант раскодировки спрайта, который проверял на попадание в видимую область указанных координат, что требовалось для проверки на точное попадание мышью.

Кроме того, все варианты раскодировки дублировались для следующих случаев:

  • Зеркальное отражение спрайта по горизонтали.
  • Спрайт частично оказывается за пределами окна. Т.е. было необходимо ручками срезать кусок, который не попадал в видимую область экрана.

В качестве ассемблера использовался tasm32.exe. Командная строка для сборки ассемблера выглядела так:

tasm32 /l /ml /zi modul_s.asm, где modul_s.asm исходный код на ассемблере. В результате образовывался объектный файл modul_s.obj, который уже можно было линковать к проекту на C++.

Само обращение к функциям из C++ выглядело примерно так:

extern «C» bool AsmSprite(параметры);

Ресурсы

Вопрос хранения и редактирования ресурсов — это, пожалуй, самый важный вопрос, который определяет в дальнейшем всё остальное. Поэтому, на мой взгляд, создание любой не самой маленькой игры нужно начинать с создания редактора ресурсов. В идеале у вас должен быть визуальный редактор, который позволит вносить почти любые изменения в игру без помощи программиста. Т.е. при создании игры заниматься самой игрой нужно, как ни странно, в последнюю очередь, а первый ваш штурм должен быть направлен на создание такого редактора. Редактор ресурсов не нужно путать с редактором карт — у них принципиально разные назначения. Редактор карт — это задача, наоборот, уже «под занавес», так как чтобы рисовать карты вам, практически, требуется, чтобы сама игра уже функционировала.

Итак, вернемся к ресурсам…

В моем случае в игре должны были обрабатываться ресурсы следующих видов:

  • Спрайты (служат изображением для всех остальных видов ресурсов)
  • Неживые объекты (деревья, камни, минералы, разные украшательства)
  • Живые объекты: юниты и здания
  • Снаряды (стрелы, ядра, ракеты, магия)
  • Апгрейды, т.е. исследования, которые можно произвести во время игры с целью улучшения характеристик юнита или здания.

image

image

Как я уже говорил ранее, на начальной стадии очень важно получить изображение, поэтому редактор ресурсов можно начинать с возможности загружать и сжимать спрайты.

Далее необходимо было подумать о том, чтобы научить редактор ресурсов создавать Живые объекты. Для этого недостаточно просто иметь набор картинок, необходимо объединить эти картинки в анимации и объяснить игре, для чего именно используется та или иная анимация.

Давайте разберемся, какие обычно действия может выполнять боевой юнит в RTS. Очевидно, что юнит должен уметь находится в состоянии «ничегонеделания» — назовем его Ожидание. Далее юнит должен уметь перемещаться — назовем это действие Перемещение. Юнит должен уметь сражаться — назовем это действие Воздействие (вообще воздействие может быть и положительное, например, Излечивание). И, наконец, юнит, которому не повезло с командиром, должен иметь действие Смерть. Эти действия представляют собой базовый набор истинного воина.

На самом деле ситуация с Воздействием была гораздо сложнее, так как существовали и дополнительные стадии. Полный цикл Воздействия мог выглядеть примерно так:

  • Подготовка в Воздействию — это, практически, подготовка к стрельбе (Арбалетчик присел для выстрела).
  • Воздействие — собственно, сам выстрел.
  • Перезарядка оружия — в настройках юнита можно указать количество выстрелов без перезарядки, затем оружие нужно было перезарядить (Арбалетчик закладывает новую стрелу).
  • Пауза между Воздействиями — здесь могла быть любая анимация, но самое главное, что данную стадию можно ускорять за счет Апгрейдов, тогда юнит начинает стрелять чаще.
  • Выход из Воздействия — цель уничтожена и новая цель отсутствует, значит можно войти в обычный режим (Арбалетчик, который присел для стрельбы, выпрямляется).

image

Для юнитов, которые слишком резко меняли своё направление, было добавлено действие Поворот, например, Танк поворачивался на месте для смены направления движения.

Свойства, которыми обладает анимация:

  1. Действие — показывает игре возможности объекта (Ожидание, Перемещение, Воздействие и т.д.).
  2. Направление движения (5 шт) — требуется, чтобы объект визуально мог отображаться в разных направлениях. Обычно для каждого направления движения потребуется дублирование анимации со всеми её свойствами, кроме, собственно, спрайтов.
  3. Завершение анимации:

  • Окончание — анимация завершается (если делать больше нечего, то обычно запускается анимация на Ожидание)
  • Зацикливание — анимация начинается с начала (полезно для Зданий, на которых может бесконечно воспроизводиться анимация Ожидание)
  • Переход — запуск другой анимации, дополнительно требуется выбрать анимацию (позволяет комбинировать анимации одну с другой, можно использовать случайную анимацию из нескольких вариантов).
  • Новый объект — в момент окончания текущий объект превращается в новый, который должен быть указан (полезная штука для случая, когда, например, Шаман оживляет Статую, т.е. требуется превратить здание в юнита).
  • Смерть — текущий объект уничтожается в памяти игры.
  • Пауза — определяет задержку анимации на данном кадре. Есть возможность использовать случайные задержки. Паузы хорошо помогают изобразить неторопливое разложение убитого воина, так как обычно труп присутствует на карте еще очень долго, после его смерти.
  • Звук — можно проиграть какой-нибудь звуковой файл. Данное свойство хорошо себя зарекомендовало в анимациях стрельбы из автомата или долбания противника мечом.
  • Функция — это конкретное действие, которое выполняется на данном кадре анимации. Можно было одновременно задано несколько функций на одном кадре (например, выпустить ракеты из двух стволов сразу). Перечислим основные функции (хотя их немного больше):

  • Воздействие — это и есть тот самый момент, когда враг получает топориком по голове. Это, конечно, самое простое использование функции Воздействия, на деле же дополнительные параметры позволяют указать тип этого воздействия. А здесь в списке есть не только Физический удар, но и Лечение, и Воровство магии, и еще куча всего. Также в тип воздействия входят такие обыденные дела, как Добыча ресурса (Работник стукает топориком по ёлочке и на нужном кадре анимации функция Добыча ресурса вытряхивает ему из дерева дровишки), а еще здесь же банальный Ремонт поломанного Здания, когда Работник возвращает Зданию жизнь. Любое Воздействие всегда направлено на текущую цель, над которой юнит выполняет действие.
  • Взрыв — по координатам текущего объекта выполняется взрыв, у которого регулируется сила и радиус ударной волны. Для взрыва также можно выбрать тип воздействия, но обычно это просто Физический удар. Логично предположить, что функцию Взрыва обычно используют не Живые юниты, а Снаряды, которые взрываются достигая цели.
  • Зарождение объекта — функция для создания другого объекта. Например, Лучник с помощью этой функции должен создать Стрелу на данном кадре анимации. Дополнительно для Стрелы надо будет указать координаты, по которым она будет создана, т.е., практически, придется еще таскать спрайт Стрелы по экрану, чтобы правильно расположить его относительно Лучника. Естественно, что позиционировать создаваемый объект относительно создающего необходимо для всех направлений движения, т.е. практически, эта операция выполнялась 5 раз. В каждом случае подбирался такой спрайт Стрелы, который больше соответствовал бы текущему направлению юнита. Стрела в игре начинала своё существование именно с этого спрайта, а далее могла самостоятельно разворачиваться, в зависимости от направления к цели.

Естественно, что юниты должны иметь характеристики, такие как сила, защита, количество жизни, скорость перемещения. Для них должно быть определено Здание, в котором они будут производиться, скорость производства, стоимость и т.д. Есть юниты, которые могут перевозить других юнитов, т.е. Транспорты. Есть вариант, когда юниты не просто перевозятся Транспортом, а еще и стреляют из него. Некоторые юниты могут летать, соответственно, для них нужно определить высоту полёта «от» и «до», в этих пределах летающий юнит может изменять свою высоту случайным образом. Некоторые Здания умеют действовать по аналогии с транспортами, т.е. юниты могут попадать внутрь, например, Лучники могут быть помещены в Защитную Башню, чтобы стрелять из неё.

Отдельного стоит кратко упомянуть об объектах Снарядах. Снаряд может поражать наземные или воздушные цели, быть автонаводящимся, т.е. следовать за целью как ракета или вести себя как катапультное ядро, т.е. двигаться по параболической траектории. Снаряд умеет выполнять только два типа анимаций Полёт и Смерть. Анимация Полёт позволяет указать Снаряду множество направлений, а не фиксированные 8 как у обычного юнита, что обеспечивает плавное изменение траектории Снаряда. В момент достижения цели Снаряд выполняет анимацию Смерть, которую можно завершить функцией Взрыв. Кроме того есть возможность дополнительно указать, что снаряд может поджигать деревья. Создаваемый снаряд всегда получает какую-то Цель в виде координат либо игрового объекта, чтобы двигаться к ней, иначе само существования Снаряда теряет смысл.

Апгрейды, в моем случае, это такие же объекты, которые создаются с помощью редактора ресурсов. Апгрейд в игре может существовать только в одном экземпляре. Апгрейд не имеет анимаций, но имеет иконку для панели управления и список производимых действий. Также апгрейд может иметь конкретный список объектов, на которые он действует. В момент, когда апгрейд произведен, в памяти игры просматриваются все объекты и для тех, на кого действует данный Апгрейд, выполняется изменение характеристик. Помимо обычных Апгрейдов существуют и очень фундаментальные. В частности, для расы Онимодов есть возможность выбрать Путь развития, коих у него ровно 3:

  • imageПуть Нападения
  • imageПуть Защиты
  • imageПуть Неизвестного

История их появления весьма необычна, и связана с тем, что одному из художников очень нравилось рисовать технику для расы Онимодов. В результате для Онимодов у меня были следующие боевые единицы тяжелой техники:

  • imageДрон
  • imageТанк
  • imageБроневик
  • imageКамикадзе
  • imageКогг

Выбрасывать столько готовых юнитов с моей стороны было бы непростительным расточительством, особенно учитывая, что для второй расы Ботсвана нужных юнитов, наоборот, не хватало. Поэтому для Онимодов я придумал такую штуку как Путь развития. Выбирая один из путей, игрок, практически, делает доступными одних юнитов и запрещает других. Например, первый путь, именуемый Путь Нападения позволял использовать юнитов Дрон, Танк и Камикадзе. Во втором пути, который назывался Путь Защиты, были доступны Дрон, Танк и Броневик, причем Танк умел трансформироваться в очень сильную дальнобойную пушку, а Броневик, практически, являлся ходячим дотом, так как может возить Солдат, которая находясь внутри расстреливает противника. Третий путь, именуемый Путь Неизвестного, позволял использовать юнитов Дрон, Камикадзе и Когг. Дополнительно этот путь обладал достаточно интересной возможностью — он позволял присылать воинов в Капсуле (выполняет у Онимодов роль Дома) прямо с орбитальной станции, которая по сценарию висит на орбите планеты. Визуально это выглядит так, что при посадке здания из него вываливаются юниты.

Влияние пути развития не ограничивалось только набором доступных юнитов — некоторые ключевые Апгрейды были доступны только в одном из путей. Например, Путь Нападения, позволял сделать Апгрейд, который давал возможность сажать в Вертолёт до 3-х Штурмовиков, ведущих огонь прямо из Вертолета. В результате выбор Пути развития сильно влиял на общую стратегию ведения боевых действий.

Управление объектами

Юниты и Здания должны выполнять те действия, которые им поручены игроком или AI. Для выполнения этих действий каждый объект имеет в своем составе массив команд. Чаще всего в массиве будет одна команда, которая и будет текущей, но, например, игрок может используя клавишу SHIFT добавить на выполнение сразу несколько команд. Завершив выполнение очередной команды, объект приступает к выполнению следующей. Если все команды выполнены, то объект автоматически добавляет в массив команду COM_WAIT или Ожидание, что в результате запускает анимацию с действием Ожидание.

Также юниты обладают возможностью самостоятельно добавлять к себе в массив команды. Эта ситуация рассмотрена в разделе AI где описываются Инстинкты юнитов. Простой пример: воины получили от игрока команду «Патрулирование» и курсируют между двумя точками. Если обнаруживается неприятель, то воины самостоятельно добавляют себе в начало массива команду Уничтожение или COM_DESTROY и атакуют цель. После того, как COM_DESTROY будет выполнена, она будет удалена из массива команд и управление опять вернется к команде Патрулирование, что приведет к тому, что воины продолжат патрулирование.

Для начала нужно разобраться, что же представляется из себя команда. Простейший случай команды — это COM_GO или Перемещение. Игрок выделил юнита и щелкнул мышкой в произвольное место карты. Это приведет к тому, что в массив команд выделенного юнита попадет COM_GO, которая незамедлительно начнет осуществляться. Эта команда очень проста, так как в качестве аргумента ей нужны лишь координаты точки на карте, к которому должен подойти юнит. Однако обратите внимание, что данная команда не имеет продолжения, т.е. она завершится после того, как юнит достигает цели. На деле же существуют куда более сложные команды, например, Патрулирование, Строительство здания или Добыча ресурсов. Все эти команды имеют несколько фаз, к примеру, Добыча ресурсов подразумевает после того, как текущий ресурс полностью добыт, найти новый ресурс и приступить к его добыче, т.е. команда Добычи ресурса, по сути, не заканчивается до тех пор, пока поблизости есть что добывать.

Или другой пример. Работнику дана команда Строить здание:

  • Работник закладывает фундамент. Если на месте закладки фундамента находятся юниты, то они отойдут в сторону, освобождая место.
  • Работник осуществляет строительство (оно же ремонт) здания.
  • Работник ищет рядом другое недостроенное или поломанное здание. Если такое здание не найдено — завершаем выполнение команды, иначе нужно выполнить Ремонт найденного Здания.

Чтобы была возможность выполнять команды любой сложности, необходимо разделить их на фазы. Значит любая команда состоит из фаз, и этих фаз может быть N штук. Сначала всегда выполняется первая фаза, но далее фазы могут выполняться в любой последовательности, так как любая фаза может передать управление на любую другую фазу. Каждая фаза может прервать команду, если нет возможности для её выполнения.

Любая фаза, в моем случае, должна уметь выполнять следующие функции:

  • INITIALIZAION — Инициализация перед началом выполнения фазы.
  • TEST — Проверка цели на пригодность выполнения над ней действия (цель может умереть или уже не нуждаться в выполнении над ней указанной команды). Чаще всего эта функция не требуется, так как большинство команд направлены на другие игровые объекты, а проверка по умолчанию типа «живой / не живой» выполняется автоматически. Команды, не требующие цель, и вовсе не нуждаются ни в каких проверках на её пригодность. Если проверка всё же присутствует, то она вызывается постоянно по ходу выполнения фазы в момент, когда обработчик команд получает управление.
  • ACTION — Основное действие фазы, которое является целевым. Выполняется, когда цель достигнута (например, оказалась в пределах зоны поражения). Выполняется один раз, как и Инициализация. Может вместо чего-то конкретного просто передать управление на другую фазу.
  • FIND — Выбор новой цели для данной команды. Обычно эта функция не определена. Выполняется один раз в случае, если цель стала недоступна для выполнения над ней действия (здание было полностью отремонтировано — нужно поискать другое поломанное здание).

Команда Добывать ресурс является одной из самых сложных. Поэтому хотелось бы разобрать именно её более подробно. Визуально добыча ресурсов осуществляется для Онимодов и Ботсваны принципиально иначе, но в основе всего этого лежит один и тот же алгоритм.

Добытчик Онимодов называется ИТР и визуально выглядит как достаточно крупный робот, который закрепляется рядом с ресурсом и осуществляет добычу. Добытые ресурсы он отправляет в Хранилище не двигаясь с места. Визуально это выглядит так, что он погружает в землю «трубу», а на Хранилище анимация этой трубы появляется на одной из шести технических площадок, что визуально демонстрирует, что ресурс доставлен.

Добытчик Ботсваны называется Работник и является как бы «классикой жанра». Он добывает ресурсы при помощи кирки и носит их в Хранилище своими ножками.

Специально в игру для обоих команд было добавлено условие, что добытчики у обоих рас могут одновременно добывать один и тот же ресурс только одним добытчиком.

Итак, игрок выделил мышкой несколько добытчиков и щелкнул правой кнопкой по минералу. Что происходит дальше? Так как я сам ввел условие «каждому ресурсу по одному добытчику», то первым делом я выбираю для каждого добытчика свой персональный минерал, чтобы каждый добытчик сразу направился к своему личному ресурсу. В качестве команды каждый добытчик получит COM_EXTRACT, которая принимает координаты ресурса и его тип как аргумент.

Очень важно то, что какая бы команда не была текущей, алгоритм обработки команд всегда проверяет, присутствует ли у команды целевой объект. Например, команды типа Маскировка (включить невидимость) не имеют целевого объекта, так как они выполняются «на себе» и при этом совершенно точно никуда не нужно двигаться. Но многие команды типа Атака или Добыча ресурса выполняют действие над целью. Это означает, что цель должна быть в пределах досягаемости. Действие над целью всегда выполняется через анимацию Воздействие, которая может создавать для этой цели объект типа Снаряд, либо наносить удар самостоятельно (киркой по минералу). В первом случае достаточно приблизиться на расстояние выстрела (distance = радиус видимости). Во втором случае, очевидно, что объект должен подойти к цели вплотную (distance = 1). Действия по командам обрабатываются только после завершения очередной анимации — анимации не должны резко прерываться. Обработчик команд всегда проверяет, находится ли цель в пределах расстояния distance. Если нет, то обработчик команд будет всегда выполнять движение к цели, т.е. юнит потихоньку пошагает в нужном направлении. Вызов обработчика команд будет происходить с периодичностью в один шаг (имеется в виду переход с одной клетки карты на другую). Опять же уточняю, что движение к цели не входит в саму команду Добыча ресурса, а является частью алгоритма по обработке любой команды.

Команда COM_EXTRACT состоит из 4-х фаз:

Фаза начинается с INITIALIZATION. Инициализация фазы всегда вызывается до того, как обработчик команд начинает движение к цели — это позволяет подменить цель. Первым делом проверяем, есть ли уже в руках какой-то ресурс. Если есть, то переходим на фазу DELIVER_RESOURCE, т.е. ресурс сначала необходимо отнести в Хранилище.

Если ресурса в руках нет, то можно добывать. Для этого нужно проверить аргументы команды. Если по указанным координатам ресурс отсутствует, то это говорит о том, что он уже добыт (возможно, что другим добытчиком). В этом случае, требуется произвести поиск другого ресурса, преимущественно того же типа, который указан в аргументах команды. Такой поиск не просто просматривает сами минералы, но и определяет факт того, что какой-то добытчик уже трудится над данным ресурсом. Т.е. выбирается именно свободный для добычи ресурс. Кроме того выполняется тестовое построение пути до выбранного ресурса с учетом того, что другие добытчики также являются препятствием на пути. Результатом выполнения инициализации фазы START_EXTRACTION является выбор ресурса, который можно добывать в настоящий момент.

Обычно добытчик находится на некотором расстоянии от ресурса, поэтому нужно подойти вплотную. Обработчик команд автоматически проверяет расстояние до цели и начинает движение, если это требуется. При каждом изменении координат юнита для фазы START_EXTRACTION вызывается функция TEST, которая проверяет на то, что ресурс остается доступным для добычи. Если TEST вернула отрицательный ответ, то для фазы запускается функция FIND, которая ищет новый доступный ресурс и вся команда Добывать ресурс перезапускается с самого начала, но с новыми координатами ресурса.

Если добытчик сумел добраться до ресурса, то для фазы START_EXTRACTION выполняется функция ACTION, которая, правда, ничего не делает, а лишь передает управление на следующую фазу.

Задача этой фазы — это дожидаться, когда ресурс станет доступен для добычи. Особенно эта фаза актуальна для Работников, так как они постоянно носят ресурсы в Хранилище, позволяя другим Работникам занять их место у ресурса.

Фаза имеет функцию ACTION, которая и осуществляет все эти проверки. Если ресурс пока занят для добычи, то функция включит ожидание на пару секунд, после чего будет выполнена повторная проверка на доступность ресурса к добыче. Если после ожидания добывать по прежнему нельзя, то осуществляется поиск другого доступного ресурса на максимально близком расстоянии и управление передается фазе START_EXTRACTION. Если ресурс освободился или изначально не был занят, то управление сразу передается следующей фазе, которая уже и осуществляет добычу. В случае, если ресурс за время ожидания оказался полностью добытым, то вызывается поиск нового ресурса и управление опять передается на START_EXTRACTION.

Представляет из себя непосредственную добычу ресурса.

Сначала выполняется INITIALIZATION, которая делает для добытчика текущим Воздействие типа Добыча ресурса.

Функция ACTION осуществляет процесс добычи, которая вызывает на выполнение действие Добыча ресурса. Все типы Воздействий обрабатываются одним и тем же алгоритмом, поэтому само осуществление Воздействия не имеет никакого отношения к команде Добыча ресурса. Однако мне кажется, что дополнительные объяснения по этому поводу позволят связать то, что я говорил уже про стадии Воздействия (Подготовка в Воздействию, Воздействие, Перезарядка оружия, Пауза между Воздействиями, Выход из Воздействия) с логикой выполнения команд.

Выполнение любого Воздействия требует разворота к цели лицом. Для Работника тут всё достаточно просто — у него Воздействие осуществляется при помощи одной анимации (машем киркой). Однако ИТР или добытчик Онимодов имеет несколько дополнительных анимаций для выполнения Воздействия.

Для начала ИТР должен закрепиться около ресурса — визуально он как бы приседает на землю для чего используется анимация типа Подготовка к воздействию. И только после этого включается анимация основного Воздействия, которая визуально выглядит как тыканье механической клешней в ресурс. Обе эти анимации (присесть и добывать) в редакторе ресурсов настраиваются так, что их прерывание игроком без выполнения переходной анимации невозможно, т.е. если игрок захочет управлять ИТР-ом, то тот сначала запустит анимацию, которая визуально выглядит как «открепление от ресурса», т.е. ИТР сначала выйдет из присевшего состояния.

Функция TEST позволяет определить 2 момента:

  • Не добыт ли еще ресурс полностью ?
  • Может хватит добывать и пора отнести добычу в Хранилище ?

Задача этой фазы — доставить собранные добытчиком ресурсы в Хранилище. Как это не странно, данная фаза во многом аналогична фазе EXTRACT, так как, практически, эта фаза вместо Воздействия типа Добыча ресурса использует Воздействие под названием Доставка ресурса. Как я уже говорил в начале, типов Воздействий в редакторе ресурсов достаточно много и каждое уникальное действие над другим объектом требует собственный тип Воздействия. Сюда же, естественно, относятся и все виды магии, которые существуют в игре.
Опять же сначала выполняется инициализация фазы через функцию INITIALIZATION, которая делает для добытчика текущим Воздействие типа Доставка ресурса. Далее необходимо определиться с Хранилищем, куда рациональнее всего доставить ресурс. Хранилищ на карте может быть много, поэтому надо выбрать самое ближайшее. Однако производить этот поиск каждый раз нерационально, так как Хранилища не перемещаются по карте и, стало быть, достаточно выбрать Хранилище один раз, запомнить его и далее носить ресурс именно туда. Собственно, я почти так и делаю, только если вдруг появляется еще одно Хранилище, то я сбрасываю найденное ранее Хранилище у всех добытчиков на карте, чтобы поиск был произведен повторно. Для большей интеллектуальности можно выполнять новый поиск еще и периодически, так как в теории добытчик может очень сильно удалиться от первоначального места добычи.

Функция ACTION выполняет действие Доставка ресурса. Для Работника здесь опять же всё относительно просто, так как в качестве цели выступает Хранилище, а у Работника анимация Доставки ресурса не создает никаких Снарядов, то он должен подойти вплотную к Хранилищу, поэтому он топает до него ножками. У Онимодов ИТР поступает значительно более интересно. Его анимация по доставке ресурса содержит создание Снаряда, но этот снаряд не разрушает цель, а обладает Воздействием типа Доставка ресурса, т.е. ударив в Хранилище он перебросит ресурс своей команде. Это избавляет от необходимости каждый раз бегать до Хранилища и обратно. Само Воздействие имеет несколько стадий. Сначала происходит подготовка к Воздействию (ИТР погружает в землю трубу), затем выполняется анимация Воздействия, которая кидает в Хранилище невидимый снаряд, летящий с очень высокой скоростью. Снаряд же обладает интересной функцией, которую я ранее не упоминал, он прикрепляется к цели, практически, происходит что-то типа посадки в Транспорт, т.е. Снаряд как бы попадает внутрь Хранилища, как будто в дот. У Хранилища заранее определены 6 посадочных мест, куда могу прикрепляться «пассажиры», и Снаряд прикрепляется к свободному месту и тут же запускает анимацию, которая на Хранилище наблюдается в виде вылезшей из земли трубы. Визуально вся схема выглядит так, что ИТР запустил трубу под землю, а она вылезла на Хранилище. Труба на Хранилище выполнив анимацию просто умирает, так как её анимация заканчивается действием Смерть. Затем ИТР выполняет анимацию Выход из воздействия, т.е. затягивает обратно трубу. Всё, ресурс доставлен. Естественно, что все анимации ИТР на стадии доставки настроены так, что игрок не сможет мгновенно получить контроль над юнитом — ИТР сначала вытащит трубу из земли, а потом уже сможет куда-то поехать.

Далее управление опять передается фазе START_EXTRACTION, но так как ИТР уже готов к добыче, т.е. находится рядом с ресурсом и уже в закопанном состоянии, то фазы START_EXTRACTION и WAIT_EXTRACTION в 99,99% случае будут пропущены и сразу начнется фаза EXTRACT. Исключение произойдет в случае, когда Хранилище находится уже слишком далеко и Снаряд просто не долетает до цели. В этом случае анимации отработают свою задачу следующим образом:

Под каждое действие, которое можно выполнить должна существовать своя команда. При этом, например, команды COM_GO (идти в указанную точку), COM_DESTROY (уничтожить конкретную цель), COM_ATTACK (идти в указанную точку, уничтожая всех на своем пути), COM_RUN (отбежать от атакующего врага, так как нет возможности защищаться) и COM_LEAVE (отойти с места, где будет построено здание) являются, по сути, разными. В моем случае в коде я наблюдаю около 50 команд, которые и обеспечивают функционирование всей игры.

Также обратите внимание, что есть даже такая милая команда как COM_CANCEL, которая просто отменяет все другие команды. Зачем она нужна? Дело в том, что в конце статьи я кратко опишу сеть, а по сети должны уметь передаваться любые действия, которые выполняет игрок, так как эти действия должны быть повторены один в один на другом компьютере.

Поиск пути

Юниты должны уметь перемещаться по карте и находить эффективный маршрут в сложных случаях. Этому вопросу должно быть уделено достаточное внимание и время. На начальной стадии я бы рекомендовал сделать любое простейшее решение, лишь бы можно было тестировать создаваемых художниками юнитов. Реальный же алгоритм поиска пути понадобится в момент создания AI, когда компьютер должен будет иметь возможность построить путь в любой самой витиеватой ситуации. Без нормального алгоритма поиска пути AI не сможет действовать эффективно, кроме каких-то исключительных случаев, когда игровое поле представляет из себя «голую степь».

Итак, у нас более менее отлажена игровая механика, юниты умеют выполнять предписанные им действия, которые они получают при помощи мыши, при этом программа не вываливается через каждые 2 минуты. Следующая стадия — это создание эффективного алгоритма поиска пути. В настоящий момент в Интернете присутствует немало советов на эту тему, я не могу сказать, насколько хороши или плохи эти методы, так как в своё время изобрел для себя собственное и, на мой взгляд, очень эффективное решение по этому поводу. Вполне возможно, что оно примерно повторяет какой-то опубликованный впоследствии алгоритм, так как решение действительно достаточно изящное. Но, как я уже сказал, все решения, которые я показываю в данной статье на тот момент я генерировал своей головой самостоятельно.

Подробная статья по моему методу поиска пути в классических RTS имеется здесь. Помимо, собственно, самого алгоритма поиска, там описан процесс управления этим алгоритмом. Этот раздел касается таких проблем, как столкновение юнитов между собой во время движения, следованию за другим юнитом (цель постоянно меняет своё положение) и прочих не таких уж и очевидных моментов. Статья писалась лет 10 назад и лично для меня имела целью «не забыть» о собственном решении. Дублировать эту информацию здесь особого смысла я не вижу, особенно учитывая, что этой информации и так достаточно много.

AI (он же Искусственный интеллект)

Давайте сначала разберемся с тем, что же такое AI. Лично я для себя определяю AI как алгоритм, который заменяет собою действия живого игрока, которые тот выполняет при помощи мыши и клавиатуры. Теперь обратите внимание вот на что… если в вашей игре юниты не совсем тупые, то они могут самостоятельно принимать некоторые решения и выполнять их без помощи игрока. К таким решениям в моем случае относятся следующие действия:

  • Воины, замечая врага в пределах видимости, должны самостоятельно вступать в бой. Более того, если какой-то воин из отряда ввязался в драку, то «коллеги по оружию» не должны стоят и равнодушно «курить» чуть в сторонке от места действия — они обязаны тоже вступить в бой.
  • Если юнит умеет лечить, то он должен автоматически вылечивать раненных воинов. Это особенно эффективно, если отдать приказ лекарю следовать за каким-нибудь воином из отряда — слоняясь вслед за отрядом Лекарь будет лечить каждого, кто в этом нуждается.
  • Работник, стоящий без дела, будет автоматически чинить раненное здание или помогать строить новое строение. В моем случае, Работник даже анализирует «степень поломанности» зданий и может прервать текущий ремонт и начать чинить здание, которое больше в этом нуждается. Это качество может быть очень полезно, когда Работники «суетятся» между несколькими Защитными башнями, которые одновременно находятся под обстрелом. Усиленный ремонт должен производиться у той башни, которая вот-вот готова рухнуть. Дополнительно алгоритм следит за тем, чтобы распределение Работников по «строительным объектам» было разумным, а не по принципу «все силы на одно здание».
  • Добытчик ресурсов должен автоматически находить рядом следующий ресурс, если текущий закончился. Если такого вида ресурса рядом нет, но есть другие виды ресурсов, то нужно посмотреть каких ресурсов у команды меньше и добывать именно этот вид ресурса.
  • Юниты, которые обладают магией должны самостоятельно следить за тем, чтобы не помереть понапрасну. Практически, когда у мага вычитается жизнь, то он проверяет количество оставшейся жизни и, если её уже критически мало, то логично рассуждает, что игрок, скорее всего, не успеет никак отреагировать. В этом случае «ничегонеделание» равносильно тому, что маг просто будет убит не нанеся противнику никакого урона, поэтому маг применяет магию самостоятельно.
  • Юнит, который может включить режим маскировки (невидимость), автоматически включит его, если по нему нанесен удар, а он не находится в поле зрения Определителя (юнита, который размаскировывает невидимых врагов).
  • Юниты умеют автоматически отходить в сторону, если они мешают возведению какого-то строения.
  • С некоторым натягом сюда же можно отнести и умение юнита следовать за подвижной целью, т.е. если одному юниту приказать следовать за другим, то тот будет ходить за ним везде как привязанный. При этом «привязанный» юнит вполне может расстреливать врагов или осуществлять лечение дружественных юнитов, а закончив это дело снова бежать за «целью».

Причины проявления Инстинктов в игре человек часто видит с точностью до наоборот. Например, когда Работник бежит чинить здание, то создается впечатление, что это является инициативой самого Работника. На деле же горящее Здание «зовёт на помощь» в небольшой радиусе от себя всех юнитов, которые имеют в своем арсенале Воздействие типа Ремонт. То же самое касается и ситуации, когда к воюющему воину подбегают на помощь рядомстоящие воины — это реакция на призыв «Помоги-и-и-те! Убива-а-а-а-ют!».

Несмотря на то, что, по моему мнению, Инстинкты не имеют к AI никакого отношения, я поместил их небольшое описание в раздел с AI, так как для многих такое размещение покажется вполне ожидаемым. Но, на мой взгляд, Инстинкты относятся к общей игровой механике, т.е. по уму их надо было описывать немного выше по тексту. А игровая механика на момент написания AI должна уже полностью функционировать включая раздел об Инстинктах юнитов. Инстинкты должны работать одинаково как для команды, которой управляет живой игрок, так и для команды, которой управляет AI. В своих решениях AI не должен опускаться на уровень Инстинктов, его задачи должны звучать примерно так «сформировать отряд и отправить его в атаку по таким-то координатам», а то, что этот отряд будет уже самостоятельно крушить всех на своем пути — это уже задача Инстинктов.

Итак вернемся непосредственно к AI. В моем случае для каждой команды, которой управляет компьютер, обработчик AI вызывается примерно 1 раз в секунду. AI руководствуется в своих действиях следующими глобальными принципами:

  • Есть команды врагов и есть команды союзников. Соответственно, врагов надо уничтожать, а союзникам приходить на помощь в трудную минуту.
  • Какая-то из команд врагов назначается основной целью для нападения, но периодически этот враг может меняться.
  • У AI есть понятие База, которое является ключевым. База является, по сути, скоплением из нескольких строений на карте. У каждой базы есть свои границы — прямоугольник, который занимает данная база. Если произошло взаимопроникновение двух баз, то AI производит их объединение. На каждой базе строится собственная оборона, а любой юнит является привязанным к какой-то базе, до момента, пока он не получил какое-то задание.
  • Основные задачи, которые выполняет AI:
    • Развитие
    • Нападение
    • Защита
    • Поиск противника
    • Определение невидимых воинов врага с помощью определителя
    • Простая атака. Отряд собирается рядом с целью атаки, но там где его не видно и затем атакует.
    • Осадная атака. Чем-то напоминает простую, но отряд, расположившись рядом с целью не бежит сразу атаковать, а ждет пока будет накоплено достаточно сил. Силы постепенно подтягиваются и когда их достаточно, происходит атака. Побочный эффект от осадной атаки это то, что параллельно происходит блокада иногда единственного входа в лагерь противника. Также AI может во время осады выкатить вперед Катапульту и начать расстреливать издалека Защитные башни противника, основные силы при этом стоят позади Катапульты и ждут реакции осаждаемого.
    • Уничтожение конкретной цели. Иногда некоторые юниты врага (обычно танки), расположены так, что они кромсают силы атакующих без каких-либо серьезных потерь со своей стороны. Этот момент отслеживается и периодически интеллект предпринимает карательные рейды конкретно против этих юнитов. Для этого используется летающий транспорт, с которого воины высаживаются прямо на целевого юнита.
    • Диверсионная атака. Карательный рейд в сердце базы противника. Для этого применяются Транспорты, которые высаживают воинов за линией обороны врага. В основном, атакуются Хранилища с большим скоплением работников. Второй вариант этой атаки – это высадка воинов на ближайший склон, откуда можно хорошо постреливать вниз и куда враг не может подняться.
    • Магическая диверсия. Может исполняться только либо Шаманом (от Ботсваны), либо Научным модулем (от Онимодов). Исполнители начинают просто околачиваться рядом с лагерем противника и иногда покидывают магию в зазевавшегося вражеского воина.
    • Суператака. Это простая атака, которая делается совместно. Перед ней происходит небольшое затишье – накопление сил. Далее все AI, находящиеся в одном союзе совершают нападение одновременно.

    Стартовые условия и их последствия (лирический раздел)

    Итак, на дворе 1998 год. Окинем беглым взглядом окружающую действительность тогдашей IT-индустрии. Intel выпустил процессор, аж, на 233 МГц, Blizzard уже известен благодаря «Diablo 1» и «Warcraft 2», а Microsoft отличилась с помощью «Age of Empires 1». Почти на всех ПК установлен «Windows 95», который некоторые уже пытаются проапгрейдить до «Windows 98». На барахолках всей необъятной родины тоннами расходятся пиратские диски, очень популярные в народе из-за низкой стоимости. Лицензионный софт может где-то и существует (например, в Москве), но, как минимум, люди даже не понимают разницу между пираткой и лицензией. Еще один важный уточняющий момент — в стране сильнейший экономический кризис, так как доллар в течение недели вырос с 6-и до 30-и рублей, соответственно, стоимость всего, что относится к «железу» выросла пропорционально доллару. Экономика лежит…

    Группа отчаянных ребят численностью 3 человека, в этот непростой для родины час, решила попробовать себя в качестве разработчиков игр. Среди них 1 человек, который надеется, что он более-менее умеет программировать (это автор статьи) и 2 человека, которые искренне любят рисовать, в том числе и на компьютере.

    У каждого из нас был собственный ПК, но характеристики соответствовали моменту. Например, моя конфигурация была такая: Intel 200-MMX, ОЗУ — 32 Мб, Видеокарта — 2 Мб, HDD — 4Гб. К слову говоря, такое чудо обошлось мне до кризиса примерно в 9000 рублей (при средней зарплате по стране в районе 700 рублей), что соответствовало 1500$. У художников ПК были куда более скромными.

    В общем-то всё, что у нас было — это желание + «современная техника». Хотя я забыл, пожалуй, о самом важном — мы были хорошими друзьями, которые знали друг друга со школы и прошли вместе также и ВУЗ. И как оказалось этот фактор оказался в результате очень важным.

    Пожалуй, стоит упомянуть о том, чего не было. А не было в то время достаточной информации. Именно той информации, от которой сейчас интернет просто захлебывается. Не было, кстати, и самого интернета, точнее он был, но у очень ограниченного числа людей, а скорость по Dual-Up модему максимально достигала 5 Кбайт/сек, к которым прилагались частые обрывы связи.

    Всё это означает буквально следующее, что нет примеров программирования, нет алгоритмов, нет видеоуроков по обучению тому, как работать с 3D Studio Max, нет готовых движков, наконец. Не у кого спросить совета на форуме. Готовых ответов на вопросы, которые сейчас сходу «гуглятся», тем более нет. Т.е. есть только разработчик и его задача, которую необходимо решать самостоятельно и рассчитывая только на свои силы.

    Вообще стартанули мы достаточно неплохо. Я потихоньку реализовывал то, о чем написано в статье, а художники предоставляли мне графику. Основная часть графики делалась в 3D Studio Max, для анимации юнитов использовался плагин Character Studio. К счастью, удалось каким-то чудом раздобыть книжку по этому плагину и более-менее разобраться. Существовала такая проблема, что 3D Max не мог толком работать на таком слабом железе, которое еще и управлялось с помощью Windows 95. При старте 3D Max возмущался, что ОЗУ должно быть минимум 48 Мб, а на компьютере его было только 16. Надо ли объяснять, с какой скоростью всё это функционировало. Исправление любой мелочи могло занять много часов. Дополнительно 3D Max очень любил схлопываться без видимых причин.

    Однако художникам очень понравился мой редактор ресурсов, хотя он и выглядел как «инструмент для внутреннего пользования». Сначала они долго не понимали, что собирать готовых юнитов можно и без меня, а после произошедшего «озарения» на этот счёт у них появился новый виток энтузиазма. Константин стал периодически притаскивать мне не просто набор спрайтов, а уже вполне «живого» юнита. На тот момент сама возможность вставлять в игру объекты без участия программиста казалась чем-то фантастическим.

    Ситуация резко ухудшилась, когда мы решили, что уже есть что показать издателю. Издатели были в Москве, и мы просто купили билеты на поезд и отправились показывать свою работу. На тот момент прошло уже года полтора, с начала всего этого действа. AI, конечно, не было еще и в помине, не было хорошего алгоритма поиска пути, но очень многое уже работало. Нам надо было выяснить, хоть что-то конкретное по поводу дальнейших перспектив нашего проекта. И перспективы были выяснены… и они в общем-то, практически, похоронили данный проект. Юмор ситуации был в том, что вроде бы издатели хотели издавать, но, когда нам озвучили условия, стало ясно, что это всё очень напоминает рабство. После возвращения из Москвы, художники, практически, прекратили работу над игрой — и в общем-то это было во многом правильное решение. Периодически, правда, мне что-то дорисовывали, но все уже понимали, что этот проект не может принести каких-то денег, которые не выглядели бы унизительно на фоне потраченных на него усилий.

    Твёрдое мнение о том, как в россии в то время производилось «издание» у меня появилось уже позже, когда мне более-менее удалось получить в голове целостную картину, которая, собственно, всё объясняла. Не могу настаивать на её абсолютной истинности, но после того, как у меня появилось это объяснение, все вопросы были сняты. Пожалуй, я потрачу еще минутку на расстановку всего по своим местам.

    Как я уже сказал — страна была просто завалена пиратскими дисками. За этими дисками «челноки» ездили в Москву, где можно было приобрести диски оптом, чтобы потом реализовать их на барахолке в родном городе. Цены на диски не сильно отличались от цен на пустые болванки, и сама цена в пределах одного рынка всегда была одинакова для любого продукта, который содержался на этом диске. Теперь вернемся к изданию лицензионных продуктов. По моему мнению, оно выглядело примерно так: у издателя в Москве было несколько своих точек сбыта (ларьков), через которые издатель реализовывал лицензионные диски. При этом выставить какую-то реальную цену на лицензионный софт было навряд ли возможно, так как:

    а) Процветают пиратские барахолки.
    б) Население страны просто не может покупать софт за нормальную цену, особенно, когда можно купить пиратский диск задёшево.

    Поэтому стоимость лицензионных дисков отличалась от пиратских далеко не в десятки раз. Причем издатель должен был сначала печатать диски, тем самым производя затраты.

    Чтобы не тянуть время, я озвучу стандартные условия, которые предлагались разработчику:

    Издатель всегда требовал эксклюзивные имущественные права. В случае, практически, законченной игры разработчику предлагался аванс 10 000 $ + роялти. Роялти (они же процент с продаж) по максимуму могли быть 25%, чаще предлагали от 15% до 20%. Проценты, в теории, должны были выплачиваться после того, как издатель погасит свои предварительные затраты, включая аванс. По поводу роялти, сразу хочется сказать, что, по имеющимся у меня данным, их никому не платили, так как для издателя в этом просто нет особого смысла. Надо понимать, что на тот момент идея о том, что издателя можно как-то проверить была полным мифом. Я сомневаюсь, что это легко сделать сейчас, но, по крайней мере, в настоящий момент об этом хотя бы можно всерьез мечтать. А так… в стране, где бизнес всячески укрывает налоги, рассчитывать на то, что удастся выявить какие-то записи о реальном состоянии продаж, на мой взгляд, наивно.

    Итак, нам как и всем предложили эти 10 000 $. Уточню, что это не в день, а ВСЕГО, а то казуальщики, которые попадают в топ на AppStore могут неправильно понять. Т.е. разработчик ставился в ситуацию, когда он должен как-то выдавать достаточно серьезную по трудозатратам игру, но предполагаемая оплата никак не соответствует этим трудозатратам. В общем-то это напрямую связано с тем, что издатель, по сути, никаким издателем не являлся, т.е. он не выполнял свою основную функцию — он не мог ничего в реальности продать, так как продажа по своим «пятнадцати ларькам» в одном городе (при наличии эксклюзивных прав) — это не издание. О каком-то продвижении вообще речи не было, хотя в общем-то это тоже обязанность издателя. Насчет продвижения в «Буке» нам сказали, что они своим подписчикам рассылают новость на e-mail — численность подписчиков на тот момент была 11 000 человек. С «Букой» вообще было достаточно весело, так как ихняя девочка-менеджер на полном серьезе поведала мне, что они Blizzard-у за издание тоже заплатили аванс 10 000 $. В общем вся эта ахинея, на мой взгляд, была направлена на то, чтобы убедить разработчика в том, что «иначе нельзя» и надо «пока потерпеть», а зато «потом» и им тоже «что-то начнет перепадать». Точных сроков на этот «потом» не называлось, но делался намёк на то, что, возможно, следующий проект, будет рассматриваться на других условиях.

    Чуть позже мне случайно стала доступна очень занимательная информация. Оказывается, некоторые очень известные пиратские компании типа того же Fargus-а, на деле являлись дочерними компаниями российских издателей. И это простое объяснение кажется мне более чем логичным, так как лично для меня оно не оставляет больше никаких вопросов.

    А еще в позапрошлом году познакомился я в Интернете с одним человеком, который, как потом выяснилось, в те самые времена занимался локализацией игр (говоря по простому, они брали заказы на перевод игры с английского языка на русский). Он мне пожаловался на то, что им за локализацию платили всего-то 5000 $. Т.е. перевести игру стоило всего лишь в 2 раза дешевле, чем её сделать. И сейчас я понимаю, почему было именно так — в россии было хорошо налажено только пиратство, но не было, по сути, никакого издания. И оно так и не появилось, а вместо него появился высокоскоростной Интернет, который открыл доступ к западным торговым площадкам.

    Что же случилось с игрой дальше?

    Последние годы я доделывал эту работу в гордом одиночестве. Почему я не бросил эту затею? Видимо потому что, я понимал, что второй раз я такое уже не вытяну, а вытянуть очень хотелось, тем более, что было уже очень много сделано. Да и, честно говоря, я терпеть не могу сдаваться и бросать начатое на полпути — это что-то вроде «дара» и «проклятия» в одном лице. Также у меня были серьезные просчеты в сроках, т.е. я предполагал, что удастся закончить гораздо быстрее, но на деле мелочи сжирали всё время. А чем дальше я продвигался вперед, тем обиднее было бы признаться себе, что «я не смог». Вот так я и дошел до конца. Под конец вынужден был кое-что дорисовывать самостоятельно — меню, например. Рисовать я, в общем-то, не умею и не особо стремлюсь научиться, но деваться было некуда.

    Музыку к игре взял у своего приятеля, который жил в соседнем подъезде — он мне дал штук 15 мелодий на выбор. Также как и многие творческие люди, он не имел никакой возможности продавать своё творчество, поэтому его мелодии были, естественно, никому неизвестны. По-моему, он их набирал нотами в какой-то музыкальном редакторе, но так как у него имелось музыкальное образование и абсолютный слух, то, на мой взгляд, произведения вполне достойны внимания. Чувствуется симпатия автора к произведениям Жан-Мишеля Жарра, а мне «космическая» тематика очень даже подходила.

    Остальная озвучка была сделана, прямо скажем, не очень профессионально, так как уже не было никаких сил этим заниматься — надо было заканчивать эту эпопею и начинать жить дальше. В основном все фразы проговорили в обычный микрофон мои знакомые, а «вопли смерти» я озвучивал сам. В результате эта озвучка многим не понравилась, хотя лично меня она совершенно не раздражала.

    Чем всё это закончилось… да в общем-то ничем. Я бросил делать игры, так как понял, что рассчитывать на кого-то кроме самого себя я уже не смогу, а игры, как минимум, требуют оформления. Примерно год после завершения не мог себя заставить ничего делать вообще, так как просто не видел смысла что-то начинать. Потом всё же пришёл в себя и решил сделать небольшой редактор спецэффектов, скорее, из «спортивного интереса», чем ради какой-то выгоды. Впоследствии этот редактор получил название «Magic Particles». После того, как я показал редактор игроделам, мне стали предлагать добавить в него API, чтобы спецэффекты можно было воспроизводить из собственных программ. Двигалось всё это очень сложно, но в результате у меня появились продажи. Игроделы периодически покупали мою технологию в основном для казуальных игр.

    В настоящий момент я продолжаю заниматься своим Magic Particles, и к моему удивлению обнаружил, что он стал уже крупнее, чем проект Земля онимодов, который, как я думал, является моим теоретическим пределом.

    15.04.2016: Важное обновление.

    Уважаемые товарищи!
    Благодаря вашей неоценимой поддержке игра сумела пройти Greenlight. С одной стороны это для меня очень радостно (особенно учитывая, что вчера у меня как раз день рождения был), а с другой… мне сейчас придется заняться игрой и попытаться исправить, как минимум, явные недочеты, доставшиеся игре по наследству от «истории развития IT». Конечно, очень лень мне всем этим заниматься, но теперь уж, видимо, «не отделаешься». Еще раз благодарю за мощную поддержку моего очень немолодого проекта!

    С уважением,
    Алексей Седов

    Благодарю за проявленное упорство в чтении данной статьи, а, также, за терпение к моему «литературному таланту».

    У этой статьи есть продолжение.

    Unity 3D

    Создание 3D игры на Unity / Урок #1 – Разработка 3Д стратегии

    Создание 3D игры на Unity / Урок #1 – Разработка 3Д стратегии

    Представляем вам курс по изучению игрового движка Unity. В курсе вы разработаете свою 3Д игру в жанре стратегии. Курс подходит для начинающих и тех кто уже знаком с движком. Вы с нуля разработаете дизайн игр, механику и все функции в игре.

    Видеоурок

    Полезные ссылки:

    • Курс по изучению языка C# ;
    • Официальный сайт Unity ;
    • Онлайн C# редактор кода .

    Информация про Unity

    Игровой движок Unity уже много лет остается одним из самых популярных движков для разработки игр разных жанров и под разные устройства.

    Впервые игровой движок Unity появился в 2005 году. С момента своего появления движок очень сильно вырос, набрав огромную популярность среди многих разработчиков. На сегодняшний день на его основе построены десятки тысяч как мобильных, так и полноценных компьютерных игр.

    Большая популярность пришла к движку из-за его простого формата разработки игр. До 2005 года уже существовали именитые игровые движки. Многие из них были очень хороши, но имели проблему связанную с их доступностью. Некоторые движки были закрыты для массового использования, другие же были доступны, но их функционал был перегружен и разработать игру в одиночку было просто невозможно.

    С приходом Unity сфера понемногу начала меняться. Все дело в том, что Unity предложил отличное готовое решение, с помощью которого человек даже в одиночку мог разработать не только проект под мобильные телефоны, но также проект под ПК или же консоли.

    На сегодня вы можете спокойно открыть Unity, изучить его и создать в одиночку игру под разные платформы, при чем функционал этой игры будет ну уж очень даже крутым.

    На что способен Unity?

    Возможности движка действительно удивляют. На его основе вы можете разработать проект, что будет содержать: пользовательский интерфейс, современную графику, мощный и насыщенный функционал, красивую визуальную и аудио картинку, набор анимаций, встроенные кат сцены и многое другое. По факту, вы можете разработать любой проект, какой только захотите. Ограничения только могут быть связаны с фантазией разработчика.

    Важным плюсом является то, что движок является кроссплатформенным. Это означает, что вы можете создать одну игру, а далее выпустить ее под разные платформы. То есть вы пишите код один раз, а игру получаете адаптированную сразу под все платформы. К примеру, вы можете выпустить игру сразу под Андроид и под iOS.

    Примеры игр

    Конечно же перед изучением чего-либо хочется более точно понимать что вы сможете получить по итогу. По этой причине я предлагаю вам взглянуть на несколько проектов, что были созданы на основе движка Unity.

    Среди крупных проектов можно отметить следующие проекты:

    • мегапопулярная игра Superhot;
    • карточная игра Hearthstone;
    • игра The Forest про выживания в дикой местности;
    • мобильная версия игры Call of Duty;
    • игра Firewatch с красивой и насыщенной графикой;
    • проект игры про Рика и Морти в формате дополненной реальности (Virtual Rick-ality);
    • мобильный нуарный проект Inside;
    • космическая игра Kerbal Space Program.

    На самом деле это лишь мизерная часть из тех проектов, которым стоило бы уделить время. На самом деле таковых проектов несчетное количество. Так что если вы решили делать игры, то начать изучать движок Unity это всегда хорошая затея.

    C# и Unity

    В Unity вы можете создать множество скриптов, каждый из которых будет обрабатывать определенные действия в вашей игре: изменение цвета для объекта, передвижение игрока, изменение звука, настройка света и так далее. Написание кода в таких скриптах проводиться на основе языка C#.

    Перед изучением данного курса я рекомендую вам ознакомиться с языком программирования C#. В таком случае писать код вам будет гораздо проще.

    План курса

    За курс мы с вами с нуля построим крутую 3Д игру в жанре стратегии. Мы с вами рассмотрим множество важных и интересных концепций игрового движка Unity.

    Важно отметить, что в курсе мы не будем рассказывать про каждую вкладку игрового движка по отдельности. Вам нужно уже примерно представляете что такое Unity. Если же нет, то перед просмотром курса рекомендуем посмотреть вводный курс по игровому движку Unity.

    Дополнительные курсы по Unity разработке

    На нашем сайте вы можете найти более углубленный курс по Unity. В нем представлено множество важных концепций, что присутствуют в самом движке. Ознакомится с программой обучения по Unity можно по этой ссылке .

    В ходе программы обучения вы научитесь делать как 2Д, так и 3Д игры на Unity. Игры будут разрабатывать под обе платформы: Андроид и iOS. За программу вы научитесь создавать анимации, дизайн, прописывать скрипты, добавлять рекламу и монетизацию и выполнять публикацию игр в магазины Google Play и App Store.

    Большое задание по курсу

    Вам необходимо оформить подписку на сайте, чтобы иметь доступ ко всем большим заданиям. В задание входит методика решения, а также готовый проект с ответом к заданию.
    PS: подобные задания доступны при подписке от 1 месяца

    Пошаговая стратегия как хобби

    Привет, хабралюди! Кто из вас не мечтал создать свою игру? А возможно ли написать браузерную стратегию, не имея при этом опыта и денег? Возможно, если очень этого хотеть.

    Под катом моя история создания бесплатной пошаговой стратегии.

    Что из себя представляет игра? В двух словах — сетевой аналог старого доброго «Panzer General».

    Но обо всем по порядку.

    Предыстория

    Некоторое время назад я играл и модифицировал серию игр «В тылу врага». Серия отличная, а тамошние танковые бои считаю прародителями World of Tanks. Но за несколько лет сетевая игра жутко надоела, даже с модами. Причиной тому был однообразный геймплей: одни и те же карты, один и тот же поток юнитов,
    все игроки всегда копили кредиты на более мощный танк или отряд пехоты, а юнит-лист каждого был строго фиксированным.
    Таким образом некоторая техника полностью исчезла из боев, а последние были однообразны и предсказуемы. Искались способы в модах кастомизировать меню покупки, дабы игрок хотя бы рандомно получал свой юнит лист и им сражался, не говоря уже о специализациях. Но увы движок этого не позволял.

    Тогда же в форумных дискуссиях и родилась идея — «а что, если к игре прикрутить глобальную карту с экономикой?».
    Стратегия на глобальной карте, тактические бои в ВТВ. Юниты доступные сторонам диктует фронт. Не успел прислать подкрепления? — сражайся тем что есть! Круто! Конец однообразию!

    Осталось только уговорить разработчиков. Но результат разговора с ними, я думаю, всем очевиден — неизвестно окупится ли.

    Я немного знаком с коллективом BestWay, и мы пришли к выводу, что стратегию то можно и в браузере реализовать, тогда «В тылу врага» придется минимально дорабатывать, всего лишь дописав API.

    Браузерную часть, без раздумий, гордо взял на себя. Договорились после каких-то моих наработок обсудить дальнейшую жизнь проекта, ведь «поболтать» все мастера.

    Имея за душой скудный опыт программирования, в свободное от работы время я все же начал свой путь.
    С тех пор прошло около двух лет.

    Разработка

    В качестве фреймворка был выбран Сodeigniter, на нем я правил несколько чужих проектов, и был некий опыт. Клиентскую часть было решено писать на JS, точнее на jQuery, ведь flash я еще больше не знал.

    Далее нужно было понять как это все должно выглядеть. Из игр подобного жанра я видел лишь «Total war» и «Карибский кризис», но все они были standalone. Продолжительное гугление дало свой результат — weewar.com. Вот оно, то что нужно!

    За основу была выбрана карта Европы и начал анализировать html. На виваре было несколько слоев. Нижний — картинки территорий, средний — юниты, самый верхний — теги area с точным контуром гексы. При этом, весь html код весил больше 500 кб.

    Я решил упростить схему и ограничиться двумя слоями: территория и войска. Но в таком случая возникла проблема клика не на ту клетку. Ведь дивы наезжали друг на друга:

    Как я решил эту проблему? Никак. Практика показала, что она совершенно несущественная. Все клики в 99% случая производятся в центр гексы или выше. Если в будущем будут жалобы, сделаю проверку координат клика.
    Карта отрисована, в глазах счастье. Движемся дальше.

    А дальше все пошло как по маслу, до того момента, когда нужно было реализовывать поиск путей. Причем нужно не просто найти путь, а отобразить всевозможные, куда юнит может двигаться.

    Как обычно, сначала строился велосипед, затем внезапно обнаружен «волновой алгоритм», и на его основе все хорошо собралось до работоспособного состояния. Далее его нужно было портировать на php, т.к. любые расчеты js легко подделываются. Переписал, выбросил все лишнее, ведь на сервере необходимо всего-лишь проверить валидность движения из точки А в точку Б. Работает.

    Очередная интересная задача — избавиться от перезагрузки страницы. Тут все оказалось достаточно просто. Запись всех игровых действий в лог, выборка аяксом свежих логов с помощью long polling, анимация на карте полученных данных. В итоге, в двух разных браузерах я видел одни и те же действия, совершаемые в третьем. И это было очень круто, учитывая, что даже на виваре не было никаких анимаций и практически невозможно было понять, что твой враг делает, кого куда передвинул и кем атаковал.

    image

    Очередное «ноу хау» по сравнению с weewar — отображения лога действий и возможность просматривать повтор. Ну кому будет удобно читать player1 move unit 23,5 -> 24,6 ?
    Пару десятков строк кода, и юзер, кликнув на глаз в логе, видит повтор анимации.

    Когда данный прототип был показан, никакого внятного ответа от BestWay я не получил. Но совершенно не расстроился. За плечами был отличный опыт программирования и стремительное решение доделать игру как независимую. Как weewar, но лучше.

    То что было дальше, помимо программирования, можно смело считать геймдизайнерской работой.
    Сеттинг был оставлен — Вторая Мировая.
    Придумывались формулы для расчета атаки, характеристики юнитов… Очередная моя гордость — разные бонусы территорий, для взаимодействия разных типов войск. Например, танк в лесу получал +2 к обороне от вражеской техники, но -2 от пехоты, что было вполне логично и имело важное значение для геймплея. На виваре лес просто давал танку -2 к обороне.

    Так медленно и печально, спустя пол года, была рождена альфа версия, где уже можно было играть и даже местами было интересно. Потратились «кровные» на покупку домена и хостинга, проект выкачен в свет, и с друзьями начали играть первые партии. Выглядело это тогда так.

    Жизнь проекта

    В первые недели количество зарегистрированных пользователей было очень мало. Никто не понимал, куда он попал и что нужно делать. Нужен был хороший мануал, и я начал смотреть онлайн проекты на их наличие, дабы хоть примерно понять как они пишутся. Пролистав несколько, мне стало нудно. Если ты уже немного знаком с игрой, тогда документация читается легко. Но для новичка — это «лес». Пришел к выводу, что нужно интерактивное обучение. Минимум текста, максимум действий. После его реализации жизнь стала налаживаться.

    День за днем игрались партии на затертой до дыр карте Европы, еще той, с weewar. Это быстро надоело. Было ясно, что без редактора карт не обойтись.
    Примерно за месяц написал такой редактор, которому игроки были очень рады. В первые сутки его существования в проекте появились 5 новых карт. На сегодняшний день карт около 40.

    Очень хотелось сделать красивую отрисовку возможный путей.
    Но уперся в производительность браузеров. Для реализации необходимо JS-ом накладывать третий слой с полупрозрачной белой гексой. А на средней карте это около 1000 новых div. Файрфокс, опера — довольно быстро справлялись с задачей. Хрому нужно было несколько секунд. Ну а виновник «торжества» — IE. Даже девятая версия добавляла дивы секунд 5. Пришлось отказаться. Думаю над более производительной схемой.

    Вот так, в течении нескольких месяцев, почти каждый день в проекте что-то делалось. Фиксились баги, прикручивались новые фичи. Добавлялись юниты. Буквально на днях был кардинально обновлен интерфейс, и добавлена новая нация — США. Полная история изменений доступна в разделе «Что нового?».

    За 2 месяца жизни проекта зарегистрировалось почти 150 русскоязычных пользователей, было сыграно 300 игр, а в логе действий оказалось 75 тысяч записей.
    Наверное неплохо, учитывая, что ни копейки не было потрачено на рекламу, а проект был представлен всего-лишь на нескольких русскоязычных форумах.

    Что дальше?

    Кто-то клеит модельки, кто-то играет в страйкбол, мое хобби — моя стратегия.

    В данный момент собираю «кровные» на хорошего художника, ведь многие юниты и объекты в игре из других игр.

    В будущем планирую реализовать еще несколько сеттингов, например, средневековье или современную войну, пока не решил. А может и орков с эльфами, с чем чёрт не шутит.

    Также в планах нужные фичи, такие как туман войны или бронирование техники. Более подробно можно почитать на сайте в разделе «В разработке».

    Проект пока крутится на обычном хостинге, поэтому даю ссылку сразу на обучение. Оно полностью на JS, не насилует MySql. Надеюсь, хабраэффект будет милостив.

    Спасибо за внимание и удачи на виртуальных фронтах!

    P.S. Огромное спасибо alexDark и Armin за помощь со статьей.

    Как разрабатывается Android стратегия?

    google

    Разработка стратегии для платформы Android – задача, подразделяющаяся минимум на N этапов. Сложность работы зависит от масштаба проекта. Очень простая стратегия может быть разработана и одним человеком за 3-4 месяца, при условии наличия у него понимания принципов проектирования игр. Данный материал – не пошаговый мануал. Описание только базовых принципов может занять около 50-70 страниц книжного формата. Поэтому за пошаговым руководством обращайтесь на Youtube или специализированные сайты. Ниже же кратко рассказано о том, что потребуется для реализации проекта.

    Какие нужны инструменты

    Создание стратегии под Андроид с нуля отнимает сотни часов чистого времени и требует глубоких знаний программирования. Проще всего разрабатывать игру с применением специального конструктора. Таковым является, например, Unity 3D. Он включает в себя движок Unity и набор необходимых инструментов для разработки. Знающим английский язык, на официальном сайте проекта доступен пошаговый мануал, учащий пользоваться инструментами приложения. Остальные могут обратиться к неофициальной документации на сторонних сайтах

    При использовании Юнити для создания стратегии под Андроид нужно писать сравнительно мало кода. Большая часть разработки в нем ведется в интерактивном режиме. Программировать приходится только поведение объектов.

    Процесс разработки

    Стратегия создается почти так же, как и любая другая игра для Андроида, но с учетом жанровых особенностей. Для получения достойного внимания проекта потребуется создать следующее:

    • дизайн уровней;
    • модели юнитов и окружения (2D или 3D);
    • код, определяющий реагирование игровых объектов.

    Это минимум, что требуется для получения в конечном итоге стратегии для Андроида. Реализация более сложных проектов также предполагает написание сценария, проектировании серверной части приложения и т.д. А для того, чтобы разработка возымела популярность, необходима еще и оригинальная идея. Создание такой игры требует от разработчика высокого уровня профессионализма, но главное – наличие у него знаний в области программирования, дизайна, рисования и/или 3D-моделирования и т.д. Мало какие люди способны обладать таким количеством навыков. Поэтому качественная стратегия может быть разработана только коллективом специалистов, состоящим минимум из 5 человек.

    При этом основная сложность в разработке стратегии для Андроида состоит в проектировании и реализации реакций юнитов и окружения. Необходимо сделать так, чтобы не было дисбаланса, и написать искусственный интеллект. В противном случае игра будет чересчур проста, а значит – неинтересна.

    Стратегия – один из самых сложных в реализации жанров. В процессе необходимо продумать множество нюансов и написать тысячи строк кода. Стратегия может быть создана в одиночку только при условии наличия у разработчика большого количества времени и глубоких знаний. Поэтому такими проектами занимаются команды, включающие в себя по несколько специалистов каждой специальности.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *