Как стать автором
Обновить
23
0
Иван Щербина @Jester92

Программист С++

Отправить сообщение

Файл с часто использьуемыми символами не менялся уже наверное лет пять. Возможно при его составлении использовался частотный словарь, но тут точно не подскажу. В дебри именно составления словарей подобного рода не залезали, а сделали fallback в системный шрифт. Это решение проще в реализации с одной стороны, а с другой - итоговый шрифт не будет распухать.

Имена у нас, конечно, есть. Здесь есть пару хитростей:

  1. Текстовый документ common.txt, в котором часто используемые символы. Их может не быть в текстах, но они могут быть в именах.

  2. Есть fallback на системный шрифт: если нет символа в собранном шрифте, то он берётся из системного. Выглядеть этот символ будет немного не так, как все остальные, но жалоб на это не было.

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

Честно говоря, не рассматривался. Когда добрались до шрифтов, подавляющее большинство было TTF, ещё пару штук OTF. Поэтому естественным образом решили пойти и стандартизировать уже присутствующие на проектах решения и сделать их лучше. Пока что получившийся вариант нас устраивает и по качеству, и по размеру. А задач по улучшению сборки ресурсов всегда много и даже не уверен, что появится время поглядеть на woff2. Но будем иметь в виду куда можно ещё покопать.

В играх изображений на порядок больше. Те проекты, которые сейчас собираю, содержат в районе 50-60 тысяч png-шек. И тоже столкнулись с проблемой места в git, и ограничений в 150/200 Мб на размер приложения. Если кратко по этапам решения:

  1. [git] Обязательно вырезаем мета-информацию. Даже есть прекомитный хук, чтобы в репозиторий в принципе не попадали лишние данные. В некоторых случаях изображение с 25 Мб урезается до 1 Мб. Photoshop любит положить меты с лихвой.

  2. [форматы] Не знаю насколько это актуально для приложений, но у нас для разных платформ сжимается в разные форматы вроде etc2, pvrtc, webp. Это позволяет сильно сокращать размеры.

  3. [сборка] Сборка ассетов выделена в отдельную конфигурацию и собирается отдельно. Плюс обязательно используется кеш (хранится пара: хеш настроек+хеш файла -> итоговый результат). Без кеша сборка около сорока минут, с кешем - пять. Это прямо спасение. В основной сборке в post-build шаге xCode/MS Build запускаем скрипт, который берёт артефакты сборки ассеты и сливает их с другими ресурсами, потом кладёт это уже в нужную папку.

В не игровых приложениях вообще применяются атласы? Они тоже помогают сильно сэкономить и места, и скорость загрузки/отрисовки.

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

Насколько я помню, при ребейз, если нет конфликта, не вызовет pre-commit. А сами проверки вызываются именно в нём. Могу сказать точно про слияния: если в них нет конфликтов и всё слияние прошло автоматически, то проверки точно не запустится. А чтобы наша система на сервере определила наличие хуков у пользователя мы ставим [-] в конце сообщения к коммиту.


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

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


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

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

Сейчас довольно много решений, позволяющих настроить сборку и внедрить туда шаги тестирования. При распределённой команде это будет особенно удобно. Всё же если цель — выпустить проект в мир, то минимальный CI нужен (хотя бы сборка со статическими проверками раз в сутки). Так больше шансов словить косяк не перед дедлайном.
А полноценный CI строится действительно очень долго и небольшими шагами, но жить сейчас без постоянных сборок, рапортующих «Аларма!» в случае сбоя, было бы грустно.
Прошу прощения, но почему статья с текстом «стало актуальна ст. 148 УК РФ», когда последний раз она менялась в июне 2013? Отчего такой интерес вызван? Пытался найти какие-либо законопроекты вносимые, которые меняли бы эту статью как-то, но тоже нет.
Соглашусь в том, что они очень похожи. Если обобщить, то обёртка это доработанный пул объектов с некоторыми ограничениями.
Согласен, в коде всё так же можно допустить ошибку. По поводу Mock-объектов, то для них возможна замена проще, чем переписывать функцию, заполняющую g_storege. Допустим, есть набор глобальных объектов, которые необходимы для реального запуска. Этот же набор дублируется для всех тестов. Данные объекты-дубликаты будут с пустыми реализациями виртуальных методов, чтобы можно было их создать. Есть объект AI, который необходимо заменить на конкретизированный для тестов.
g_storage.RemoveGlobalObject<AI>();
g_storage.AddGlobalObject<AISpecific>();

AISpecific будет выдавать тип AI в методе RecalcHashCode. Поэтому всё хранилище заменять не надо будет. Естественно, остаются сложности с поддержкой двух функций-регистраторов и подобной заменой объектов. Однако в случае с глобальными переменными это уже лучше, чем ничего.
Не совсем. Допустим, у нас есть GameInfo, который содержит информацию об игровых объектах. И есть система AI, которой нужны игровые сущности. В случае глобальных объектов нету уверенности, что сначала создастся GameInfo и AI не будет при создании использовать не инициализированный указатель. В случае с обёрткой вы можете написать
	g_storage.AddGlobalObject<GameInfo>();
	g_storage.AddGlobalObject<AI>();

И уже определённо сначала создастся GameInfo, а потом AI. При удалении будет обратный порядок
	g_storage.RemoveGlobalObject<AI>();
	g_storage.RemoveGlobalObject<GameInfo>();

При таком создании-удалении у AI время жизни меньше, чем у GameInfo, и возможно использование одного глобального объекта другим без боязни получить nullptr.
Хотите эксклюзивный доступ? Забираете (запрашиваете + удаляете) объект из пула и используете сами.

То есть пул не отвечает за уникальность объекта и нужно самому потом следить за этим. Тут и есть проблема. Задача же стояла в том, чтобы заменить именно глобальные объекты, а не все подряд. Чтобы у программиста при использовании не было мыслей про то, что и где он должен проинициализировать или сохранить. В вашем варианте, как минимум, нужно ещё одно место, откуда будет забираться и удаляться объект из пула, а потом доступ к объекту нужно будет совершать через эту сохранённую переменную. В итоге, мы приходим всё к тем же минусам глобальных объектов, что и при использовании оных через extern переменные или синглтоны, но ещё через одну обёртку.
А в случае, если мест использования несколько? Кто тогда отвечает за то, что это место будет одно? Что помешает в пул добавить несколько одинаковых объектов? Ведь данный паттерн будет решать данные вопросы только в случае доработки и введения данных ограничений.
1. За инициализацию объектов отвечает программист. Но так как у вас есть контроль за порядком создания объектов, то это облегчает весь процесс.
2. Если есть объекты, которые зависят друг от друга, то и удалять и регистрировать и удалять их можно в соответствующем порядке. Опять же, в данной обёртке у вас есть контроль за порядком создания и удаления, поэтому избежать обращения одного глобального объекта к другому, когда последний уже удалился, проще.
Насколько я понимаю, пул объектов предназначен для того, чтобы во время использования получить готовый объект, а не создавать его. В пуле может быть множество объектов одинакового типа. Также он рассчитывается на достаточно большое количество объектов. Расчёт при разработке был в другом — небольшое количество объектов, которые будут храниться в единственном экземпляре. Здесь есть что-то и от пула объектов, и, как уже писали, от паттерна Dependency Injection.
Предположительно, в проекте не будет больше 30-40 глобальных переменных. В том же CryEngine насчитал в структуре около 45. С этим расчётом разрабатывалось и тестировалось. В случае, если количество глобальных объектов переваливает за сотню, то, возможно, с архитектурой проекта не всё хорошо.
В любом случае замечание дельное и в ближайшее время постараюсь потестировать с большим количеством объектов и разными контейнерами. Благодарю за отзыв.
Компании может и не нуждаются в самих хабрах, но нуждаются в людях, которые читают хабр. Конечно, для разработки графики не требуется очень много спецов, но они нужны (посмотрите вакансии топовых компаний). А начинающий специалист должен с чего-то начинать, для чего и предназначен данный цикл уроков. Прошу прощения, если я вас не так понял.
Но кто-то же должен писать готовые движки? Для этого нужно разбираться, как это делать. Если раньше только иногда вспоминалась «Академия» Азимова, то сейчас, при прочтении подобных комментариев или статей, прямо уже вижу картину, как физики-ядерщики возводятся в ряд жрецов.
1

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность