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

от admin

Разработка браузерной стратегии

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

Что представляет собой игра? Видимо наиболее коротким описанием будет «клон Цивилизации» =). Но это не значит что у меня не хватило фантазии придумать что-то свое. Просто сделать «Цивилизацию» было моей мечтой. Вряд ли бы я получил столько удовлетворения от написания другой игры. Ну а фанаты Цивилизации наоборот считают, что моя игра совсем не похожа на Цивилизацию, разве что только с виду. Может это и к лучшему.

Игра называется The Fate of Nation http://fatenation.com

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

Для создания игры я использовал php и MySQL на сервере, html и javascript на клиенте. Flash не используется. Из html5 есть только видео на сайте и несколько областей с канвасом в самой игре — включая поверхность карты и мини-карту. Объем кода клиентской части в несколько раз превышает серверную часть, поэтому в основном буду рассказывать о клиентской разработке, но начнем с сервера.

Общая архитектура

Общая архитектура приложения выглядит как полностью асинхронное веб приложение на JavaScript. Перезагрузок страниц не предусмотрено. Обмен данными с сервером исключительно через Ajax и JSON. В JSON’е передаются только данные, без html кода. Html разметка загружается отдельно в начале загрузки приложения и процессится с данными через клиентский шаблонизатор по мере загрузки данных с сервера.

image

На сервере никаких фреймворков не использовал — хотя начинал писать с использованием Zend Framework, который выкосил потом за ненадобностью. Вместо него создал свою простую архитектуру отдаленно напоминающую контроллеры и экшены из ZendFramework.

Как видно из рисунка, на сервере одна точка входа — файл index.php. В процессе игры на сервер идут запросы вроде такого: /Unit/Move. И посылается JSON с параметрами, в данном случае это id юнита и координаты перемещения. Сервер перенаправляет этот запрос на index.php, в котором последовательно выполняется подключение к БД, проверка текущего пользователя и парсинг строки запроса для определения контроллера (Unit) и действия (Move). Если контроллер не задан то сервер выдает индексную страницу с кодом для построения клиентского приложения, но об этом позже. Если же контроллер задан то ищется файл этого контроллера, подключается его код и запускается обработка запросов этого контроллера, где соответственно ищется необходимый экшн, а в нем производится проверка входных данных и дергается бизнес логика.

image

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

Теперь немного о самой игре.

Карта

Первое что было сделано это карта на которой происходят почти все игровые действия: строительство городов, улучшений (посевы, дороги), перемещение юнитов и исследование карты. Размер карты составил 1000 на 1000 клеток для каждой отдельная запись в БД. Я видел игры где карта сделана бесконечной и записи о клетках динамически вставлялись тогда, когда с клеткой производились какие-либо действия. Но меня такой подход немного пугал своей непредсказуемостью. Гораздо проще планировать игру, когда точно знаешь, что у тебя есть фиксированная карта. Можно запланировать расположение игроков их количество, количество городов и юнитов, приблизительно оценить нагрузку.

Итого получилось 1000 * 1000 = 1 000 000 записей в БД для карты. До этого я не работал с таким количеством записей и меня это насторожило. Думал что будет тормозить.

image

Я решил перехитрить MySql и разместить карту в 10-ти таблицах по 100 000 записей в каждой с надеждой, что станет быстрее работать. В итоге пришлось написать дурацкую логику по выборке клеток из нескольких таблиц сразу, а замеры показали что производительность только упала. Вернул все назад в 1-у таблицу.

image

  • x, y — это координаты клетки.
  • terrain — тип территории (луг, лес, гора. ).
  • resource — ресурс если он есть на клетке (глина, лошади).
  • wens9_code — название поля произошло от west-east-north… 9 — означает что изображение данной клетки зависит от территорий 8-ми рядом стоящих клеток и естественно от территории самой этой клетки — всего 9. Эту логику я спер с 3-ей цивилизации, насмотревшись их спрайтов территорий там где по 512 вариантов иконок для одной клетки!)) Потом у меня вскипел мозг разбирая зависимости по которым они выбирали иконки и я понял, какой это большой геморрой. =) И все только для одного: чтобы спрайты имели жесткие концы в виде ромбиков 128 на 64 пикселя. В конце концов мы решили использовать png24 с полупрозрачными краями накладывающиеся друг на друга и создающих в 10 раз лучший и разнообразный ландшафт, чем в описанном примере из Цив3. А выбираем иконки случайно независимо от соседних клеток. Это видно на скрине — сразу не скажешь где там одинаковые иконки полей. Вот горы по краям размыть забыли и они имеют четкие границы — что плохо смотрится.
  • starting_position — означает что в этой клетке появится игрок.
Регионы

Клиент написан таким образом, что он не запрашивает с сервера определенные клетки, а запрашивает их партиями по 100 штук (10 на 10), которые я назвал регионами. То есть каждая клетка принадлежит какому-то региону и клиент запрашивает регионы и не конкретные клетки. Как только игрок перемещает карту так, что становится виден новый регион, мы посылаем запрос на сервер за этим регионом и граничащими с ним. Данные каждого загруженного регионакешируются на 30 секунд на клиенте. Это позволяет легко прокручивать карту без тормозов и лишних запросов на сервер и избавляет от задержки при появлении нового региона на карте — так как мы загружаем все соседние наперед.

Когда я делал эти «регионы» я не предполагал насколько они увеличат производительность. Оказалось выделить 100 клеток фильтруя по полю региона получается многократно быстрее чем фильтруя по координатам. Несмотря на то, что я объединил x и y координаты клетки в одно поле location = 1000*x + y. Сделал это прежде всего для удобства — чтобы легче было достать одну клетку.

image

Затем каждую сущность (города, юниты, ресурсы), которые располагаются на карте и имеют соответственно конкретные координаты, я также пометил регионом, что увеличило производительность выборок в сотни раз. Одно дело искать значения в таблице по ключу с миллионом уникальных значений и другое дело по ключу с 10 000 значений.

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

Исследование карты

Однако меня терзал еще один вопрос. Мне позарез хотелось сделать исследование карты — чтобы изначально она была не разведана и нужно было ходить по ней чтобы что-то увидеть.

image

Такого я не видел еще в браузерных играх (собственно как и юнитов передвигающихся по карте, а не по воздуху). Я принялся за расчеты. Стартовая позиция игрока расположена внутри региона. То есть максимальное количество игроков 10 000 как и регионов. Каждый игрок может разведать всю карту. Итого 10 000 * 1 000 000 = 10 миллиардов записей может быть в таблице пермишенов на клетки! Таблица карты показалась на фоне этого детским лепетом =). Конечно эта цифра завышена. Вряд ли кому-то удастся разведать всю карту — она очень большая. Но десятки и сотни миллионов записей в таблице пермишенов точно могут быть в конце игры.

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

image

Провести нагрузочное тестирование чтобы определить на каком этапе сервер начнет тормозить не удалось еще. Максимум что я видел это чуть более 2-ух миллионов записей в таблице пермишенов.

Перемещение юнитов

Чтобы сделать перемещение юнитов пришлось тоже подумать и переписать логику несколько раз.
Первое что нам нужно, это точно отслеживать время открытия новых клеток чтобы можно было отфильтровывать клетки, юниты и города по этим данным. Сразу напрашивается использовать таблицу пермишенов на карту, но со спец-полем — означающим время когда эта запись станет активной. Так и было сделано. Клиент отправляет id юнита, и новую координату дислокации. Сервер просчитывает текущую позицию юнита, координаты клеток по которым он будет перемещаться, и в зависимости от территории этих клеток, типа юнита и других параметров высчитывает время когда этот юнит будет в каждой клетке. Затем дополнительно просчитываются таким же образом соседние клетки в зависимости от радиуса обзора юнита.

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

Далее записи пермишенов, которые говорят о перемещении юнита мы помечаем еще 2 полями: id юнита и типом записи: ‘обзорные клетки‘ или ‘клетки по которым идет юнит‘. Первое поле нужно чтобы при остановке юнита или смене пункта назначения можно было их удалить, второе нужно чтобы при выборке юнита записать ему времена смены дислокации.

image

Затем коллеги по работе мне подсказали еще один довольно очевидный момент: ввести поле означающее время выхода юнита с данной клетки. Я назвал его out_timestamp. Это позволило легко выбирать текущие позиции всех юнитов и соответственно фильтровать вражеских юнитов по видимым нами клеткам.

Уверен, что мой пример не самая удачная архитектура для подобной игры, но вроде работает =) В следующих статьях могу рассказать о клиентской архитектуре, кешировании, используемом фреймворке и о том, как мне удалось сделать демонстрационную версию игры работающую без запросов к серверу, чисто на клиенте.

Читать:
Почему миллиард а не биллион

Да, кстати, часто после различных постов об игре народ начинает хвалить графику, а не геймплей. Так что скажу сразу — я ее не рисовал. Это все наш художник-дизайнер Максим Кудрицкий.

Тактическая стратегия за три дня

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

Доброго времени суток! Меня зовут Дмитрий, мне 28 лет и я… нет, пока еще не алкоголик, а Разработчик. С DTF я знаком уже более десятка лет (помню ещё старый дизайн), но статью пишу впервые.

Готовьте кофе и бутерброды — сегодня я расскажу о том, как полтора года назад команда из трёх человек смогли создать тактическую стратегию за 3 дня и 3 ночи.

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

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

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

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

Роли оказались распределены следующим образом:

Я взял на себя код, часть 3D-графики и level-дизайн.

Денис (второй разработчик) — 3D-модели предметов и окружения.

Вениамин — написание музыки, озвучка и помощь с 3D-графикой.

Усвоив на своих и чужих ошибках, что сном во время разработки пренебрегать не стоит (ещё успеется на последних этапах), мы основательно выспались и узнали тему джема на несколько часов позже, чем она была представлена участникам.

Как и на многих других конкурсах, сформулирована она была достаточно абстрактно: «Человечеством правят. «

В процессе командного обсуждения «на троих» озвучены следующие идеи:

  • Деньги — Подходит под тематику, но в данном направлении полёт мысли не развивался.
  • Тайные общества — Интересно, но трудно реализуемо в столь малые сроки.
  • Игроки — Буквальное толкование темы, за которое мы ухватились. Игрок, управляющий группой людей. Почему нет?
  • Вирус — Именно заражённые (зомби) в итоге оказались в игре.

Спустя 3 часа мозгового штурма суть игры была полностью сформулирована в двух словах:

«Оборона блокпоста».

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

Потратив все силы на споры и разногласия, мы всё-таки успели сделать несколько моделей и основы геймплея.

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

Стройка на даче знакома многим, а стройка на даче будущей тёщи.

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

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

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

Тем временем другие члены команды тоже не теряли времени даром — к моему возвращению уже был готов саундтрек для главного меню и новая порция 3D-графики.

Остаются последние сутки, а игры ещё нет.

Код не закончен, уровень недоработан, озвучка не записана.

Время бессонной ночи! Написав за день основную часть геймплея и оставив остальное «на потом», я пришёл к тому, что за ночь предстояло всё отполировать, сделать модели растительности, противников и наконец приступить к несчастному level-дизайну.

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

(Из многолетнего опыта я понял, что система частиц слишком «плавно» следует за вращением оружия, а текстура при большинстве ракурсов выглядит плоско)

Когда всё уже было почти доделано, выяснилась неприятная ситуация — юниты не атакуют друг друга. Вернее пытаются, что-то делают, но.

Обнимашки с зомби!

Ошибка оказалась нестандартной. Время, проведённое за компьютером, уже перевалило за 15 часов. Поиск решения занял кучу времени, из-за чего пришлось пожертвовать:

  • Подбором припасов и аптечек. Под корень пошла вся механика, завязанная на этом.
  • Озвучкой. Под нож пошли даже звуки выстрелов.
  • Размером уровня. В конкурсной версии он оказался очень компактным.

К созданию противника мы подошли оригинально — «раздели» солдата, перекрасили (говорят, у проектов с «чёрными» шансов больше), и получился мутант в противогазе.

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

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

Хотя призовое место наша игра не заняла, участие в джеме позволило мне сделать ряд полезных выводов:

enepomnyaschih

В этой статье вряд ли я затрону нечто неизведанное. Все выкладки просты и понятны любому, кто знает, что такое Ajax. Я уже писал статью о том, как следует совмещать клиент с сервером в реал-тайм играх (http://enepomnyaschih.livejournal.com/1610.html). В данной статье я решаю те же самые проблемы применительно к пошаговым играм.

  • Пошаговая стратегияэто стратегическая пошаговая игра.
  • Стратегическая играэто жанр игр, в котором залогом достижения победы является планирование и стратегическое мышление.
  • Пошаговая играэто жанр игр, основной особенностью которого является то, что игроки совершают ходы по очереди.
  • Пошаговые стратегии
  • Карточные игры
  • Настольные игры (шахматы, го, монополия и пр.)
  • др.

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

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

Приводимые рассуждения имеют под собой опору 2-месячной разработки некоторой карточной игры.

Умный или глупый клиент?

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

Это напрямую зависит от того, сколько весит полный объем данных о состоянии вашей игры. Если этот объем данных велик, долго собирается на сервере и передается клиенту, то имеет смысл часть логики реализовать на клиенте, чтобы разгрузить сервер. Например, в Civilization датчик используемой памяти всегда зашкаливает. Сможете ли вы создать нечто подобное, оставив на клиенте исключительно UI?

С другой стороны, чем умнее клиент, тем дороже обойдется разработка игры. Замечу, что от эрудиции клиента время разработки сервера никак не зависит. Пусть даже клиент супер-пупер-мега умный, если пользователь захочет перезагрузить окно браузера, то серверу прийдется собирать и компоновать все данные об игре для передачи их клиенту. А ля «Загрузка сохраненной игры». Вывод: умный клиент может ускорить работу приложения, но он всегда потребует дополнительных ресурсов для разработки приложения.

Предлагаю следующий тест:

1. Позволяет ли объем канала?

Оцените средний вес полного объема данных о состоянии игры. Далее, умножьте на среднее количество запросов к серверу в секунду. Если полученное число превысит объем исходящего канала передачи данных, то глупый клиент недопустим. Если это число превысит 20% исходящего канала, то стоит призадуматься, потянет ли?

2. Велика ли трудоемкость?

Оцените трудоемкость алгоритма сбора данных об игре (в долях секунды). Здесь же учтите все запросы к базе данных. Далее, умножьте на среднее количество запросов серверу в секунду. Если время превысит одну секунду, то глупый клиент недопустим. Если это число превысит 200 мс, то стоит призадуматься, потянет ли?

Создание стратегической игры ⁠ ⁠

Создание стратегической игры Gamedev, Стратегия, Пошаговая стратегия, Лига геймеров, Геймеры, Война, Тестирование, Своя игра, Длиннопост

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

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

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

Однако качественное реализация еще не гарантирует успех. Необходимо отстронится от личних ожидании и увидеть мир игры глазами обычного игрока. Что увлекает его? какие эмоции заставляют обычному человеку прилипнуть к игре?

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

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

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

Похожие статьи