Неделя 11 (декабрь 2): Склады.
Когда мне говорят что я идиот, обычно, я верю. И вот мне на полном серьезе говорят что если я не могу придумать систему для организации инвентаря в игре, значит я не играл в РПГ. Да, я действительно не догадался посмотреть на устройство инвентаря Diablo III, потому что делаю вроде как ферму и ориентируюсь на вроде как простые игры (ага, ферма — простая игра, ну да, чо уж там, 11я неделя и я столько всего простого сделал).
Но разобравшись в итоге в том, как можно сделать инвентарь, я понял, что чувак, так болезненно задевший меня, играющего в компьютерные игры без малого 30 лет, тем что я типа не играл в РПГ, что я третью неделю не могу успокоиться, этот чувак… может и играл в РПГ, но он не умеет заниматься проектированием (еще больше чем я) и не знает как устроен инвентарь Diablo III.
***
В общем, чтобы понять как должен быть устроен игровой инвентарь, нужно ответить на ряд вопросов. С выполнением ряда условий, которые находятся в основе того как этот механизм может быть устроен с технической точки зрения.
- Прежде всего механизм должен быть единым. Склад ресурсов и предметов должны работать одинаково.
- Второе условие заключается в том, что предметы должны храниться где-то не напрямую, а через айдишники. Ведь я могу просто сделать переменную типа «Предмет» в которую поместить объект хранения, а могу сделать переменную типа Int и хранить в ней айдишник. Теоретически, на этапе игры, расположенной на компьютере, я могу хранить и то, и другое, но я мечтаю о том, что моя игра будет серверной и хочу чтобы логика сразу была готова к хранению в виде таблиц базы данных. Хотя на самом деле и на сервере можно хранить просто помещенный в переменную объект. Все равно для обработки этих данных их придется помещать в объект.
- Ну и да, я заморачиваюсь вещами, которые реальную пользу могут и не принести никогда.
Вопросы же получаются такими:
- Какие будут склады?
- Простой ответ на это такой: склады ресурсов и склады предметов. Есть более сложные варианты, например: сумочка персонажа. Что мешает ей тоже быть складом? Из этого следует что у склада должен быть какой-то владелец.
- Какими свойствами обладают сами склады?
- Мне на ум приходит три свойства: уже упомянутые тип хранимых предметов и владелец склада, а так же объем хранения. Последнее означает что при добавлении предметов необходимо проверять есть ли на складе свободное место.
- Если склады имеют ограничение по объему, то в чем оно выражается и как определяется объем хранимых предметов?
- Как реализовывать склады в которых предметы занимают какой-то геометрический объем, мне даже представить страшно. А вот со значением веса все значительно проще. Просто у меня все предметы будут иметь вес 1.
- Как предметы хранятся на складе: поотдельности или объединяясь в пачки?
- В моем случае предметы должны объединяться в пачки. Причем все: и ресурсы, и предметы. Ресурсы понятно почему — их будет много и хранить и отображать их по-отдельности будет плохо. С предметами примерно та же история. Если по началу каждый предмет может выполнять довольно индивидуальную роль, то со временем игрок будет производить одинаковые предметы в больших количествах. Они уже не будут иметь для него индивидуальной ценности и их надо будет объединять.
- Если предметы собираются в пачки, есть ли какие-то ограничения на максимальный размер пачки?
- У меня ограничения не будет, но вообще в некоторых играх оно встречается. В той же Дьябле, например.
- Будет ли у склада механизм ячеек?
- Тут речь про что-то типа пояса, когда игрок может положить пачку каких-то предметов в ячейку. На этом механизме работают пояса в некоторых играх. На этапе фермы мне этот механизм не нужен совершенно, а будет ли он мне нужен потом — это вопрос для будущего меня.
- Как игрок получает новые склады?
- В моем случае склады игрок получает при строительстве построек. Если я буду делать сумки персонажей через склады, то при появлении у игрока нового персонажа, игрок должен получать и новый склад.
- Как предметы будут добавляться на склады?
- В моем случае добавление предмета на склад — это его создание. Создаваться предметы могут в результате крафта, открытия сундука и при покупке в магазине. Это больше работа с сами предметом чем со складом, но склад добавляет сложностей, например: что будет если игрок хочет создать предмет, а на складе нет места или вообще нет подходящего склада?
- Как предметы перемещаются между складами?
- Ответ на этот вопрос значительно зависит от того как будут реализованы ответы на другие вопросы. Но я собираюсь делать простые команды: одеть, снять, переместить — пока не знаю какие проблемы это может вызвать.
- Как предметы расходуются?
- Ответ на этот вопрос обманчиво прост, особенно в моем случае. Ведь я мечтаю о том, что у меня один предмет может иметь разные свойства: редкость, силу, ценность — оставаясь одним и тем же артикулом. И вот для производства шкафа нужны гвози, а в инвентаре кроме простых гвоздей есть золотые?
- Как игрок видит склады?
- Это тоже довольно интересный вопрос. Доступ в общеигровой инвентарь получается через меню инвентаря, а не через интерфейс постройки к которой относится склад. Вот есть у игрока склад с предметами — шкаф — содержимое которого игрок видит через меню инвентаря. И вдруг игрок строит второй шкаф. Не должны ли одинаковые артикулы хранящиеся в разных складах отображаться в этом меню как один артикул с суммарным количеством?
Вопросов получается довольно много. И это хорошо. Работа геймдизайрена заключается в том, чтобы генерировать такие вопросы и придумывать на них ответы, до того как они придут в голову исполнителям. А они придут. Программная реализация не терпит неоднозначностей и… если честно список этих вопросов я составил уже реализовав механизм складов. Перед началом работы у меня было всего несколько вопросов и ответов на них. Не уверен что смог бы составить этот список целиком сам до начала работы.
Наверняка, есть еще какие-то вопросы, которые я даже после окончания работы над механикой, не догадался задать сам себе.
***
И так получилась система при которой создание объекта приводит к созданию связанного с ним склада. В некоторых случаях этот склад можно назвать слотом. Например кроме сумки под всякий лут, который может попасться персонажу в его приключениях, у него есть еще куча отдельных сумок единичного объема и строгой типизации под оружие и шмотки. Таким хитрым образом я решил проблему определения того, чем является слот персонажа.
Тут интересно то, что я не знаю, можно ли догадаться отнести слоты персонажей к механизму складов на этапе его дизайна? Ведь с дизайнерской точки зрения это совершенно разные вещи, а с точки зрения кода — одна.
Но создать слот в который можно будет запихнуть 50 бутылок эликсира здоровья я наверное не смогу. Хотя это вопрос проверки артикулов при добавлении предметов на склад. Но необходимости в этом пока нет.
Внутреннее устройство придуманной мной системы таково, что при добавлении в инвентарь, предмет (или пачка) будет искать свободное место в подходящем инвентаре. Если же свободного места не будет, или не будет умещаться вся пачка, то остаток будет искать следующий свободный инвентарь и создаст в нем новую пачку. Таким образом в складах построек (если их несколько) один предмет может оказаться в нескольких экземплярах разного количества.
Мне это не очень нравится, но другого решения я не нашел (на самом деле это решение было неверным и делать надо было ровно наоборот, я из будущего, см. неделю 15).
И в итоге общеигровой инвентарь игрока будет отображаться как один с суммарными объемами как предметов (благо это даже программировать не надо, у меня уже есть поиск суммарного количества артикулов), так и самих складов.
На видео показывается как шмотка для которой нет склада никуда не добавляется и исчезает. А при наличии склада, шмотка успешно добавляется в него.
В общем, самым сложным было сделать алгоритм поиска подходящего склада и распределения предметов по складам при наполнении одного из складов. При том что я все еще не знаю, нужно ли мне это будет. Кажется пора уже задуматься об игровом балансе (запомните этот момент, я из недели 21).
***
Сделать склады персонажей было совсем просто, но тут всплыла еще одна моя недоделка, без которой мне будет трудно и грустно: у предметов должна быть система действий — одеть/снять, разобрать, открыть, съесть и т.п.
В старой доброй рыбалке действия перечислялись битовыми флагами: 2 (0010) — одеть, 4 (0100) — разобрать, 8 (1000) — открыть. Подобную систему я использовал в своем Сапере (если кто не вкурсе у меня есть почти — арта не хватает — сделанный сапер) чтобы хранить в клетке всю информацию о ее соседях одним числом.
Используемый мной QuickSheet вроде бы умеет считывать массивы из конфигов. На этом «вроде бы» я и застрял. Перечислить через запятую названия команд и читать их из массива — звучит приятно же. Но массив почему-то не создается…