Найти в Дзене
ZDG

Блог разработки Crypt Quest Remake: Шрифт

Предыдущая часть: Для игры я решил сделать новый шрифт. Игровые шрифты я всегда подразумеваю растровыми, так как подгружать полноценные векторные TrueType + библиотеку рендеринга это перебор, и в целом не отвечает духу ретро-игры. Плюс свой шрифт всегда можно нарисовать конкретно таким, каким хочешь, а не искать что-то смутно похожее на желаемое. В общем, я нарисовал то, что мне кажется типа-вроде-будто шрифтом каменных замков и подземелий, с некоторой долей рукожопой неуклюжести, что должно придавать самобытности. Выглядит, пока ещё в тестовой версии, как-то так (русские буквы тоже будут): До сих пор я делал 1-битные шрифты. Это значит, что каждая точка растра кодируется одним битом – если 1, там есть пиксел, если 0, то нет. Закрашивать же этот пиксел можно любым цветом. Такое решение позволяет максимально компактно хранить шрифты, в отличие от случая, где каждый глиф был бы полноценной картинкой. Но на этот раз я решил сделать немного иначе. Каждый пиксел шрифта будет кодироваться це

Предыдущая часть:

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

Плюс свой шрифт всегда можно нарисовать конкретно таким, каким хочешь, а не искать что-то смутно похожее на желаемое.

В общем, я нарисовал то, что мне кажется типа-вроде-будто шрифтом каменных замков и подземелий, с некоторой долей рукожопой неуклюжести, что должно придавать самобытности. Выглядит, пока ещё в тестовой версии, как-то так (русские буквы тоже будут):

-2

До сих пор я делал 1-битные шрифты. Это значит, что каждая точка растра кодируется одним битом – если 1, там есть пиксел, если 0, то нет. Закрашивать же этот пиксел можно любым цветом.

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

Но на этот раз я решил сделать немного иначе. Каждый пиксел шрифта будет кодироваться целым байтом, и этот байт будет обозначать прозрачность от 0 до 255. За счёт этого края глифов будут выглядеть сглаженными.

-3

Но есть нюанс

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

-4

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

Стандартным образом это делается путём составления кернинговых таблиц для пар глифов, таких как AV, AT, To, Wa и т.д. Там для каждой пары указывается расстояние, на котором должны находиться буквы. Лучше всего определить это расстояние вручную, визуально, но мне пока лень этим заниматься, и организация кернинговых таблиц, поиск в них пар и т.д. грозит вылиться в непропорционально большой объём работы.

Исходную картинку с шрифтом я нарисую так, что у букв будет определённый отступ слева и справа. Например, заметно, что у букв C, O, S отступ слева должен быть чуть больше.

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

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

В первом приближении получилось так. Зелёным я пометил буквы, которые сдвинулись.

-5

Видно, что идеально сочетаются QU, GICA, OW, но что случилось с WA? Если приглядеться, то и BA, и BE, и ON, и особенно LY заежают друг на друга. Это произошло потому, что детектор коллизий неверно работает на одном столбце. Например, у буквы A весь левый столбец пустой, кроме самого нижнего пиксела. Поэтому он невозбранно будет двигаться внутрь предыдущей буквы до тех пор, пока именно этот нижний пиксел с чем-то не столкнётся. В случае с сочетанием WA результат плачевный, так как у W именно нижние пикселы справа пустые.

Увы, придётся проверять не один столбец, а всю прямоугольную область пересечения. Ну и после некоторой возни, вот новый результат:

-6

Всё ещё не идеально, но уже можно читать почти не морщась.

Читайте дальше: