понедельник, 11 октября 2010 г.

Game from Scratch: In The Begining

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

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

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

Кому будет сие интересно? Это будет возможно любопытно людям, которые занимаются разработкой MMO-игр. В некотором смысле будет любопытно и для УЕБ-девелоперов. Мало любопытно будет любителям python'ов, twisted'ов и так далее.

In the begining
in principio erat Verbum et Verbum erat apud Deum et Deus erat Verbum
В данной статье мы поговорим о начале и началх и о том как от бесконечного балабольства перейти к делу. С самого начала свой возни в программировании, мне ужасно нравилось работать с данными, формализовывать их, выносить из кода константы во всевозможные конфиги и базы данных. Частично это называется Data-driven programming.

Но совсем в начале нужно поставить задачу. Т.к. у меня есть слово, пожалуй им воспользуюсь. Задача наша до ужаса банальна и проста и любит ей заниматься любой школьник с 14-16 летнего возраста. Мы хотим сделать игру!11 Пока мы не знаем как она будет выглядеть (поищите по форумам, большинство энтузиастов мрут на моменте - я не могу найти художников и программистов для того чтобы сделать супер-пупер аналог кризиса). Но знаем что это ММО игра. Предположим (нагло), что это будет "обычная" игрулька вроде Lineage 2 или World of Warcaft. Давайте запомним, сейчас у нас нет художников, денег и вообще нифига (или они есть но больше ничего нету) и мы хотим хоть что-нибудь делать. И делать мы будем то, что называется ядром.

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

Т.к. тут я повелитель клитора, то позволю себе окунуться немного в историю. Первыми полноценными ММО были всевозможные MUD'ы. Реализовывались они с помощью Си и представляли в себе монолитный блок который считывал данные из сокета и реагировал на команды игрока, параллельно выполняя некоторые задачи. Если вы школьник и хотите получить пищу для ума, поищите всевозможные ROM-based сервера и поразвлекайтесь их кастомизацией. Ежели голову не сломаете, научитесь программировать и даже немного понимать C.

Появление рынка видеоигр спровоцировало и создание MMORPG. Так появились всякие Ультимы. Ультимы были уже сложнее, но все еще продолжали наследовать прошлое. Приход же в мир эмуляторов Lineage 2 (как и утечка исходных кодов Lineage 2) подарили миру первое сегментирование ядра. Появился некий ужасный login service. Который иногда не работал и потому на остальной монолитный сервис попасть было нельзя.

Lineage 2 представлял собой одну большую емкость, содержащую в себе всех игроков, весь мир, всех мобов (даже если они были разделены по сервисам). И поэтому если где-нибудь случался на ГФШ большой сбор с участием игры мышцами, все игроки ощущали будто нырнули с головой в вату.

Появление World of Warcraft кардинально изменило ситуацию. Программисты и инжинеры Blizzard и раньше были бесподобны, но тут перевели разработку кардинально на новый уровень. Каждый материк WoW существовал как отдельная миска. Поэтому проблемы в миске А, не влияли на отличную работу миски Б. Последующие поколения создателей ядер MMO продолжали сегментировать логику.

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

Сервисы будут генерировать события и пересылать их тем сервисам, которые в этом заинтересованы. Внезапно мы откажемся от идеологии системы Request/Response в пользу идеи Event Only. В результате получи не синхронную среду, в которой каждый сервис будет отвечать за синхронизацию своего участка данных. Это безусловно приведет нас к проблемам, но любые проблемы нужно решать по мере их возникновения.

А скрипач, скрипач не нужен..

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


  1. Python2.7 - язык позволяющий писать хороший и простой в понимании код, не требующий огромных познаний в синтаксисе. А при должном усердии со стороны пейсателя и минимизирующий риски создания неведомой и непонятной хуйни;
  2. Twisted - но дабы всем было весело, будет у нас еще и неведомая и непонятная хуйня. Эта библиотека содержит не только асинхронное сетевое ядро, но еще и бесценную вещь - спосбность превратить вашу программу в полноценный сервис с логгированием, вашими собственными циклами обработки и во многом создать каркас для разработки.От чего-то мы откажемся (например от демонизации с использованием twistd и повсемостного втыкания zope.interfaces), что-то используем;
  3. Json - для работы сервисов нужен протокол. для передачи данных нужна сериализация. Т.к. мы используем twisted сетевой уровень нам не важен. Это может быть традиционный для туториалов LineReceiver протокол или суровый как Ъ бинарный протокол Length-Type, или еще чего-нибудь. Так же не важно TCP это или UDP. Важно как мы будем собственно сообщать сервису что случилось. Для этого мы будем создавать конструкцию в виде dict содержащего поля необходимые для всей идентификации. Для сериализации этого, нам и пригодится json. А сие можно будет отправлять соответственно хоть в Flash, хоть в Java, хоть в C++. Трудно представить языка программирования не имеющего десериализатора json сегодня;
  4. Xpath и ETree в libxml2 и python-lxml - для создания всевозможных данных (Data-Driven ога-ога) мы будем формализовывать их в виде XML. А еще частично будем хранить их в виде XML таблиц в памяти и производить быстрый поиск посредством xpath. Вы как хотите, а я люблю XML ^^
  5. NoSQL. Т.к. не известно чем все закончится. Наверняка нам понадобиться хранилище данных для игроков. Хранить структуры игроков мы будем благополучно в NoSQL хранилище. Каким оно будет, покажет момент, когда мы до него доберемся. 
  6. PyQT4 - В один прекрасный момент нам нужно будет создать игровой клиент. Т.к. у нас все еще нет графики сделаем его может быть с использованием PyQT4.
Вот такой у нас будет инструментарий. И давайте постараемся обойтись только этим.
Гена, вот то самое полотенце, которое ты просил
Чтобы уже начать что-то делать давайте разберемся с тем, с чего начнем.

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

Это первый набор данных с которого мы начнем. И приступив к началу оговорим и первый элемент того что мы делаем.

До встречи.

Комментариев нет:

Отправить комментарий