Основной целью библиотеки BearLibTerminal является (по крайней мере, так задумывалось) предоставление приложению окна, напоминающего внешним видом системную консоль, но куда более настраиваемого и заточенного больше под разработку roguelike игр. Вот, к примеру, как это окно может выглядеть. Найдите 10 отличий от оригиналов =)
Такое окно, впрочем, только лишь выглядит как терминал. То, как оно работает, сильно отличается от обычной системной консоли. Библиотека не предоставляет стандартных потоков ввода/вывода для чтения и записи. Вместо этого предоставляется сетка индивидуально адресуемых ячеек-знакомест, сцена.
Точнее, сцена это не одна сетка ячеек, а целый набор таких сеток, именуемых слоями. Для простой игры, вероятно, не потребуется более одного слоя, но иногда они могут быть незаменимы.
Каждая ячейка, в свою очередь, может содержать набор тайлов. Так как библиотека полностью поддерживает альфа-канал (прозрачность) изображений, возможность положить в ячейку несколько тайлов фактически означает возможность комбинации нескольких изображений в одно. Что сравнимо с генерацией изображение из частей на лету, например вместо подготовки всех возможных комбинаций. Следует отметить, что каждый тайл в “стопке” может иметь свой собственный цвет.
Более того, каждый тайл может иметь свое собственное смещение относительно некоторого положения по умолчанию в ячейке.
Теперь рассмотрим откуда эти тайлы берутся.
В библиотеке BearLibTerminal каждому коду символа может быть назначен свой тайл, например тайл для '@' или тайл для '#'. Диапазон кодов символов, используемый библиотекой – это basic multilingual plane Юникода. Это означает, что в наличии имеется около 65 тысяч слотов для тайлов.
Назначить одиночный тайл слоту очень просто:
terminal_set("0x5E: tile.png");
Что фактически замещает предыдущее содержимое слота новым изображением. В приведенном примере это был символ “циркумфлекс” или, по-простому, “крышечка”. С этого момента новый тайл может использоваться как и любой другой символ:
terminal_put(2, 1, 0x5E); terminal_print(2, 2, "once again: ^");
Что даст примерно следующий результат:
Следует отметить, что размер тайла практически не ограничивается библиотекой. Можно использовать тайлы размером хоть с целое окно, например в качестве фонового изображения в меню. По умолчанию тайл выводится центрированным в ячейке, но это может быть легко переопределено.
Назначение новых изображений-тайлов слотам поодиночке может быть утомительной задачей и вообще контрпродуктивно. BearLibTerminal позволяет загружать разом целые тайлсеты. Пусть есть некоторый тайлсет, состоящий из четырех изображений 16×16. Он может быть загружет практически так же, как и одиночный тайл:
terminal_set("0x1000: tileset.png, size=16x16");
Единственным отличием оказывается указание размера отдельного изображения в картинке-тайлсете. Библиотека разрежет картинку на кусочки и назначит их кодам символов. Порядок, в котором BearLibTerminal будет нарезать тайлсет фиксирован: строка за строкой, слева направо. По умолчанию тайлы назначаются последовательным слотам. В приведенном примере тайлы будут ассоциированы с четырьмя кодами символов, с 0x1000 по 0x1003 включительно.
Нет существенной разницы между одиночным тайлом и тайлсетом. Один тайл это просто маленький тайлсет из одного изображения.
Номер, указанный в качестве стартового кода символа, идентифицирует тайл или тайлсет. Для того, чтобы удалить тайлсет, достаточно просто указать, что в этом слоте ничего нет:
terminal_set("0x5E: none; 0x1000: none");
В использовании растровых тайлсетов в качестве шрифта есть один нюанс. Дело в том, что BearLibTerminal использует кодовое пространство Юникода для тайлов. Обычно можно просто написать:
terminal_print("Unicode: β"); // UTF-8Библиотека для вывода греческого символа “бета” попытается использовать тайл из слота U+03B2, по номеру назначенному стандартом Юникод. Но большинство растровых шрифтов представляют собой одну картинку с более-менее плотно упакованными символами, например:
Хотя символ “беты” имеет код 0x03B2 в Юникоде, в картинке шрифта он может располагаться где угодно. Например, в шрифтах для Dwarf Fortress, один из которых и продемонстрирован выше, символ “бета” располагается во второй колонке пятнадцатой строки, т. е. под номером 225. Что далеко от 0x03B2. И как ни выбирай стартовый код символа для тайлсета, расположить все символы в соответствии с их кодами по Юникоду не получится.
Для решения этой проблемы используются кодовые страницы, таблицы соответствия кодов символов двух кодовых пространств. В данном случае это таблица соответствия индексов тайлов в картинке кодам Юникода. Указав кодовую страницу при загрузке тайлсета можно заставить библиотеку разместить тайлы не в последовательных слотах, а в соответствии со списком:
terminal_set("font: Nobbins.png, size=9x12, codepage=437");
Коды в кодовой странице трактуются как смещение от стартового кода символа тайлсета. В приведенном примере библиотека возьмет соответсвие 225 индекса Юникоду (0x03B2 для кодовой страницы 437) и, добавив его к стартовому коду (где “font”
это просто синоним числа ноль), поместит символ “беты” в корректный слот.
Так сложилось, что шрифты для Dwarf Fortress выполнены в кодовой странице 437. В библиотеку встроено несколько кодовых страниц, а именно 437, 866, 1250 and 1251. Однако, можно использовать любую кодовую страницу, например составленную вручную, указав имя файла с таблицей:
terminal_set("font: font.png, size=9x12, codepage=custom.txt");
Как можно заметить, используемый библиотекой основной шрифт – это просто тайлсет, загруженный со стартового кода символа “0”
. В библиотеке имеется встроенный растровый шрифт, сгенерированный из шрифта Fixedsys Excelsior с кодовой страницей, идентичной набору символов WGL4. Этот шрифт устанавливается автоматически при инициализации библиотеки.
Своеобразной киллер-фичей BearLibTerminal является возможность использовать шрифты TrueType в качестве источника для тайлсетов. Можно использовать их в качестве основного шрифта:
terminal_set("font: UbuntuMono-R.ttf, size=12");И библиотека самостоятельно растеризует необходимые тайлы и поместит их в нужные слоты. Пример этого уже приводился в самом начале страницы:
TrueType тайлсеты работают практически так же, как и растровые. Можно загрузить несколько таких тайлсетов, назначив им разные стартовые коды символов. Однако, есть и различия.
Простейшее отличие заключается в том, как TrueType тайлсет понимает параметр “size”
. В данном случае этот параметр означает размер, в который будет растеризован векторный глиф шрифта, и этот размер можно задать двумя способами:
size=12
: задает среднюю высоту строчной буквы, в пикселях. Следует отметить, что в зависимости от гарнитуры, результирующий размер тайла может сильно отличаться.size=8×16
: задает непосредственно размер тайла. Библиотека постарается подобрать максимальный размер шрифта, который вписывается в указанные рамки.Другим отличием является то, что смысл указываемой кодовой страницы фактически обратен таковому для растрового шрифта. Современные TrueType как правило имеют встроенную кодовую страницу для Юникода, так что библиотеке BearLibTerminal нет необходимости в помощи со стороны программиста, чтобы понять куда какие тайлы идут. Это также означает, что загрузка TrueType тайлсета начиная с какого-то произвольного стартового кода символа добавит смещение к изначально правильному расположению тайлов. Поэтому кодовая страница для TrueType-тайлсета описывает обратное соответствие: от кодов Юникода к относительным индексам. Это позволяет загрузить выбранный набор символов из TrueType шрифта в несколько последовательно расположенных слотов. Например:
terminal_set("0xE000: fontawesome.ttf, size=16x16, codepage=fontawesome.txt");с учетом следующей “кодовой страницы”
0xF00C, 0xF062, 0xF001, 0xF0E7, 0xF013, 0xF043
поместит ровно шесть пиктограмм из шрифта FontAwesome в слоты с 0xE000 по 0xE005 включительно.
Как было отмечено выше, тайлы имеют свойство выравнивания в ячейке. Все тайлы в тайлсете имеют одинаковое выравнивание, задаваемое при загрузке тайлсета:
terminal_set("0xE000: tileset.png, size=10x20, align=center");Выравнивание по умолчанию –
“center”
и может быть опущено. Это выравнивание в основном полезно для тайлов символов, потому что тогда они располагаются привычным образом плюс скрадываются некоторые отличия в размере отдельных тайлов.
Другие возможные значения выравнивания – это “top-left”
, “bottom-left”
, “top-right”
и “bottom-right”
. Выравнивание по верхнему левому углу полезно для тайлов, размером существенно больших одного знакоместа, например тайлов уровня или изображений монстров в книге.
Выравнивание может быть еще немного настроено посредством указания размера региона выравнивания. По умолчанию размер региона 1×1 клетка, но он может быть переопределен:
terminal_set("0xE000: tileset.png, size=20x20, align=center, bbox=2x1");Что может быть удобно, скажем, при выводе монстров размером в несколько клеток или символов дополнительного шрифта.