Будни архивариуса. Три волшебных буквы, часть 2

Будни архивариуса. Три волшебных буквы, часть 2

Самопал — Будни архивариуса. Три волшебных буквы, часть 2
"В прошлой статье вы узнали о форматах файлов, полезных игроразработчику. Создав все трехмерные модели, текстуры и курсоры для своей игры, вы обязательно зададитесь вопросом, где все это хранить..."
Игроманияhttps://www.igromania.ru/
Самопал
Будни архивариуса. Три волшебных буквы, часть 2

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

   Маринад для моделей

   Заглянем в игровые каталоги. В куче файлов даже самому разработчику нелегко найти необходимый ресурс. Все игровые ресурсы нужно разложить по полочкам. Текстуры — в одну стопочку. Модели — в другую. Поскольку моделей-то у нас пара сотен, нужно их классифицировать. Сюжетных персонажей — в одну стопку, плохишей — в другую, ну а для главгероя совершенно необходимо выделить отдельную папку. Что нам даст такая сортировка? Для начала, это просто удобно. Представьте: художнику срочно потребовалась какая-то модель. На досуге руководитель проекта просматривал очередную контрольную демку и "потрепал" художника по загривку за несоответствие его фантазий суровой реальности. Текстуры нужно перерисовывать. И вот художник уже чешет тыковку, пытается вспомнить, куда модель засунул и как обозвал. А дело-то давно было.
   Чтобы в вашей практике не было таких несуразностей, обязательно каталогизируйте все игровые ресурсы. Вы можете выбрать необязательно такую схему каталогизации, как я сейчас описал. Вместо методики "Все ушки — в пучок" можно применить тактику "Все ушки — к макушкам". Допустим, вы разрабатываете кинематографичный экшен, и в какой-то момент по сюжету с главгероем должен встретиться заместитель-главного-редиски. Сначала они эффектно переговорят друг с другом, а потом скриптовый персонаж превратится в персонажа обыкновенного, а главгерою придется его "успокоить". Моделлер создал модель плохиша, художник нарисовал ему шкурку, аниматор просчитал ее скелет, а сценарист с программистом на пару разработали тот самый скриптовый ролик. Прямолинейный компоновщик уже тянется расфасовать ресурсы по каталогам, руководствуясь только расширением файлов. И нужно вовремя его остановить. Ведь это как раз тот случай, когда простая сортировка файлов по типам не только не поможет, но и навредит. Гораздо лучше выделить отдельный каталог для плохиша и отправить туда и модель, и текстуры, и скрипты, и анимацию. Теперь, если кому-то из участников проекта надо будет срочно изменить один из параметров плохиша, он знает, где искать.
   Но продуманная система каталогов — это еще только полдела. Давайте разработаем для ресурсов систему имен. Мы же разложили файлы с ресурсами по каталогам. Теперь никакой даже самый забывчивый разработчик не заплутает в рощах текстур и моделей.
43 Kb
TResManager в деле.
Так-то оно так, но перестраховка никогда не повредит. Приведу только два примера, когда система имен может быть полезной. Когда в тематической папке лежат несколько файлов с ресурсами разного типа, их сложно перепутать. Расширения-то у всех файлов разные. Но представьте себе, что через некоторое время после выхода игры вы решили выпустить сервис-пак с новыми текстурами, моделями и звуками. Все это добро лежит в одной-единственной папке. Как растолковать недалекому юзверю, что и куда кидать, чтоб работало? Вы можете все подробно описать в прилагающемся readme.txt. Но, во-первых, кто читает ридмишники? Во-вторых, станет ли ленивый игрок читать длинный список файлов и директорий, а потом заморачиваться их копировать, когда рядом лежит любимая игра? А если имя каждого файла своим названием говорит, что я, мол, текстура оружия, меня кидай в такую-то и такую-то папку, тогда другое дело.
    Если вы выбрали первый путь, решили рассортировать ресурсы по типам, в одной папке вовсе не окажутся подобные файлы. Например, в папке с моделями у вас будут модели и техники, и персонажей, и оружия. Представьте себе, что все это еще и как-то связано логически. Например, каждой модели пехотинца предназначены несколько моделей оружия. Если модели с оружием назвать по названию самого оружия, при необходимости что-то подправить придется лезть глубоко в доки и смотреть, кому же этот ствол прописан. А это — потеря времени. Лучше один раз задать всем моделям системные имена. Я бы назвал файлы с моделями оружия примерно так: название модели-владельца_тип оружия_название оружия. И тогда художник, взглянув на файл Salivan_minigun_thompson, сразу поймет, что эта пушечка — пулемет "Томми", а принадлежит он некоему Саливану. Примерно так же следует назвать все игровые файлы.
   У подхода есть еще один плюс: если в каком-то редакторе ресурсов вы откроете список всех моделей, то не запутаетесь — ведь ряды типов и подтипов одинаковой длины как будто сами формируются в стройные таблицы.

   Пресс для текстур

   На полках ресурсов царит военный порядок. Но они все еще занимают много места и открыты для любопытных глаз. Попытаемся ресурсы утрамбовать. Обычно они пакуются одним из стандартных алгоритмов архивирования, например zip или rar. Модули для zip общедоступны, и у хорошего программиста не будет проблем с их внедрением. Просто скомпрессировав все ресурсы, мы уменьшим их в несколько раз. Не только сэкономим драгоценное дисковое пространство, но и подтвердим железную дисциплину ресурсов, потому что формат zip поддерживает внутренние каталоги и подкаталоги. Мы перенесем всю организационную политику внутрь архива. И внутри архива мы сможем обращаться к файлам так же, как и снаружи — с указанием каталогов, подкаталогов и продвинутых имен по нашей системе.
   Вы никогда не задумывались, почему такая большущая картинка успешно утрамбовывается в мааленький файлик? Как это хитрые программисты до такого дошаманились? Конечно, они сделали полезное дело, а архивирование теперь помогает нам строить и жить, но все-таки, почему? Наверняка тут замешан какой-то хитрый алгоритм.
   В одном архиве может использоваться не один, а десятки и даже сотни методов сжатия. Они не имеют никакого отношения к волшебству или шаманизму, как иногда кажется со стороны. И спасибо за такую полезную вещь, как архивирование, мы должны сказать не только программистам, но и математикам. Конечно, чтобы понять самые носатые их алгоритмы, надо сперва пару раз сойти с ума и навеки уйти в монастырь... или ближайший математический ВУЗ. Но с основами попроще.
   Если вы хоть раз любопытства ради заглядывали в
41 Kb
Внедрить TResManager так же
просто, как два байта переслать.
нетекстовый файл, например в ту же картинку, то замечали кучу непонятных символов и странных закорючек. Продвинутый программист по символьному коду картинки расскажет, что там нарисовано. Но на то он и продвинутый программист. Давайте на время предположим, что за этими невнятными закорючками ничего великого не стоит. Вглядитесь в них, и вы заметите, что последовательности символов очень часто повторяются. Возьмем такую строку aaabbabbbaaababababaabbbbabbbb. В ней ровно 30 байт. Задача архиватора — всеми правдами и неправдами уменьшить ее размер. Каким бы ни был метод, общая формулировка задачи всегда одна: устранить незначащие элементы потока данных, которые потом можно будет восстановить. Надо избавиться от избыточной информации, которую потом можно будет воспроизвести на основе информации оставшейся. На первый взгляд, избыточной информации в этой строке нет. Убери одну букву — и какой-то внутренний смысл потеряется. Но это только на первый взгляд. Сперва у нас идут подряд три символа "a". Может как-то можно кратко сформулировать, что:
   Есть символ "a",
   Таких символов три штуки.

   Можно. Мы можем просто написать 3a. Разархиватор поймет, что 3a надо развернуть в aaa. Подстрока занимала три байта, а теперь она занимает два байта. То же самое проделаем с остальными повторяющимися символами. Размер строки уменьшился, но, может, можно еще как-нибудь ее подсократить? У нас остались последовательности babababa и abbbbabbbb. В них есть повторяющиеся подстроки, а значит, мы можем превратить их в соответственно 4(ba) и 2(abbbb). Последнюю подстроку можно еще больше оптимизировать: 2(a4(b)). В итоге из первоначальной строки у нас получится что-то вроде 3a2ba3b3a4(ba)2(a4(b)). Из 30 изначальных символов мы сделали 22, и при этом нисколько не потеряли в информационной целостности. Разархиватору достаточно проделать обратный процесс, и он получит первоначальную строку.

   Печать для звуков

   Ресурсы мы замариновали и утрамбовали, но по-прежнему не скрыли от чужих глаз. Ведь архивировать мы будем общедоступными методами, а значит, любой разбирающийся геймер и уж тем более разработчик запросто вскроет наши ресурсы. Поэтому архив надо закодировать. Мы можем выбрать общедоступные методы кодирования или придумать свои. Алгоритм zip предусматривает кодирование архивов. Они кодируются на пароль заданной длины. С помощью специальных программ можно вскрыть такой код. Защита zip не идеальна. Но какая защита вообще идеальна? Если правильно подойти к делу кодирования, то и алгоритм zip будет очень сложно разгадать. Время, которое понадобится программе, чтобы вскрыть пароль, напрямую зависит от длины пароля. При пяти-шести символах пароль обнаруживается методом подбора за час-полтора, в зависимости от мощности компьютера. Но если в пароле 15 и более символов, на его подбор даже у самого современного компьютера уйдет несколько лет непрерывной работы. Так что такую схему кодирования можно назвать почти стопроцентной.
    Впрочем, вы можете перестраховаться и закодировать файл с ресурсами собственными алгоритмами. Я не буду детально повествовать о них — по этой теме пишут книги, но о самых простых методах расскажу. Самый примитивный способ кодирования — замена символов в файлах согласно какой-то индексной таблице. Скажем, символ "a" мы заменяем повсеместно на символ "#", а символ "b" — на символ "@". Способ хорош тем, что реализовать его можно за считанные минуты. Минусы тоже очевидны — вскрыть пароль специальными программами не составит труда, если взломщик хотя бы примерно знает структуру файлов в архиве. Другой распространенный способ — кодирование шестнадцатиричной последовательностью с логическим методом XOR. Считается, что такой код вскрыть невозможно, если длина кода равна длине строки.
   Мы разобрали теоретические основы хранения ресурсов. Давайте посмотрим, как все это воплотить на практике.

   А ларчик просто открывался...

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

   Подарок читателям

   Каким же способом хранить все основные ресурсы? Свой формат создавать
16 Kb
Менеджер ресурсов.
— сложно и долго. В недрах exe-файла много не поместится. Самое лучшее решение — использовать какой-нибудь уже существующий архивный формат, например zip. Но его надо как-то внедрить в игру и разработать утилиту для быстрого архивирования. Всем этим придется заниматься вашему программисту.
    Здесь вас ждет сюрприз. Вашему программисту, похоже, не придется заниматься внедрением zip-системы, потому что удобный интерфейс для работы с ней уже существует. Перед автором этой статьи в свое время встала проблема комфортной работы с архивами, и он (то есть я) уже написал все необходимое для ресурсовода. Комплекс ResManager как раз предназначен для подобных целей. Он состоит из двух частей: программы-менеджера, с помощью которой можно создавать и редактировать архивы, а также накладывать на них пароли, и компонента для Delphi TResManager, который умеет работать с такими архивами.
    В программе "Менеджер ресурсов" вся структура архива отображается в виде файлового дерева, причем самый первый объект — root. С помощью контекстного меню вы можете добавить любое число вложенных папок и файлов любого размера. Предварительную структуру архива вы можете сохранить в файл-список особого формата. Когда архив будет полностью завершен, через меню "Ресурс" задайте пароль. Чем больше символов в пароле — тем труднее его вскрыть. Поэтому придумайте сложный пароль, состоящий из 12-17 символов. Пароль не должен быть словом или сочетанием слов, потому что такие пароли легко подбираются по словарю. Самый хороший вид пароля — что-то вроде в?ол3ep&*1>_yen_’4;$@/-I^. Такой пароль вскрыть практически невозможно, если, конечно, в ближайшее время не изобретут быстрого алгоритма разложения числа на множители. Если какой-нибудь гений создаст этот алгоритм, в чем я сильно сомневаюсь, головная боль будет не только у вас, но и у всего информационного мира.
    Когда структура архива полностью готова, вы можете его окончательно скомпилировать одноименной командой из меню "Ресурс". Получившемуся архиву присвойте какое-нибудь нестандартное расширение. Даже если кто-нибудь догадается, что это zip-архив, ничего страшного не произойдет. Злоумышленник сможет открыть его в WinZip, но на этом все и закончится. Любопытствующий не сможет даже извлечь ресурсы из архива, потому что для этого придется ввести очень длинный пароль.
    С помощью компонента TResManager прямо во время работы своей игры вы можете извлечь любой игровой ресурс из архива и использовать его по назначению. И вам не придется заморачиваться временным разархивированием ресурса и удалением его развернутой копии по окончании работы. Эту работу возьмет на себя компонент. Вы можете получить доступ к любому ресурсу всего одной командой. Например, вы сможете загрузить в картинку на форме какую-нибудь текстуру из архива: image.Picture.LoadFromFile( resmanager.getfile('Фон\Fon.bmp')). Если во время работы произошла ошибка, вы можете узнать о ее характере из значения переменной errorcode, которая передается в событие OnError. Если загрузка ресурса критична по времени, вы можете предварительно подготовить его, например, при загрузке игровой карты. У конечного игрока в папке C:\Windows или в корневом каталоге игры должны оказаться две динамические библиотеки: ZipDll.dll и UnzDll.dll. Я думаю, для вас это не проблема, ведь вместе эти библиотеки занимают всего 250 Кб.

   Мы еще не раз вернемся к теме архивирования собственных игровых ресурсов на страницах нашего журнала. А пока — пользуйтесь подарком. Лучший способ архивирования данных сложно себе представить.
    P.S. Комплекс ResManager находится на нашем компакте.
Комментарии
Загрузка комментариев