1. Набор символов
Абсолютно вся графика в игре выполнена с помощью символов, которые набираются на клавиатуре. Если быть более точным, то используются символы из таблицы ASCII с 32-го по 126-ой символ.
Однако, тексты в игре локализуются на несколько языков. Сейчас я параллельно поддерживаю русский и английский, но хочу добавить еще несколько, в том числе и китайский. Символов из ASCII таблиц, даже расширенных, явно не хватит для этих целей.
Диалоги в игре могут содержать символы не из аутентичного диапазона. Однако, эти символы не участвуют в дизайне. Графика — только ASCII.
2. Субсимвольная точность
В отличие от текстовых режимов в игре ASCIIDENT используется пиксельная точность перемещения текстовых слоев и движущихся спрайтов.
В текстовом режиме смещение спрайта на одну позицию выглядит как ощутимый скачок. Для такой динамичной игры как ASCIIDENT — это неприемлемо с точки зрения современного игрового опыта. Поэтому для отдельных спрайтов и текстовых слоев, о которых пойдет речь дальше, я сделал плавное перемещение.
Для сохранения аутентичности я придерживаюсь следующего правила. Внутри одного текстового слоя все статичные объекты четко выровнены по символьной сетке. Более того, каждый спрайт состоит из символов, также выровненных по символьной сетке.
Относительно же друг друга слои и движущиеся объекты могут находиться на субсимвольном расстоянии. Это обеспечивает плавность движения и, соответственно, комфортный игровой процесс. Вот такой компромисс.
3. Параллакс
В игре присутствует несколько текстовых слоев, которые двигаются с разной скоростью, реализуя эффект параллакса. Символы верхних слоев перекрывают символы нижних. При субсимвольной точности критерий перекрытия — это наложение более 50% от ширины и/или высоты текстовой ячейки. Используя простой z-буффер, легко реализовать это перекрытие.
Параллакс с плавным движением слоев — очень выразительный графический прием. Да, он, возможно, сильно нарушает аутентичность текстовому режиму. Тем не менее, я решил использовать параллакс. Очень уж красиво получается.
4. Анимация
Анимация отдельных спрайтов в игре «честная», выполненная строго в текстовом режиме. Позиция каждого символа выровнена по текстовой сетке. Анимации получаются за счет замещения символов в ячейках.
Я посчитал это очень важным, сохранить честность анимации спрайтов. Наверное, это основное, что делает игру такой ретро-привлекательной. Более того, при таком типе анимации становится технически очень просто создавать и редактировать анимационные ASCII спрайты. Я не удержался и сделал в игре встроенный ASCII редактор. В любой момент времени любой графический элемент может быть загружен в него и изменен. Можно, например, отредактировать сундук, добавив кадры анимации, и после сохранения все сундуки во всех местах игры станут новыми. Это может сделать любой игрок, создавая тем самым свой мод игры.
Однако, иногда нужна плавная анимация! Например, в игре есть такое место, где выращивается биологическое оптоволокно. Над грядками летает дрон, который орошает оптоволокно токсичной жидкостью. Жидкость должна капать плавно, иначе некрасиво. Для реализации таких эффектов я сделал генераторы спрайтов и их привязку к любым другим спрайтам в мире игры. Технически каждая капля — это отдельный спрайт, который может двигаться с субпиксельной точностью. Снова разумный компромисс.
5. Свет, цвет и шрифт
Многие люди, которым я показываю игру, делают замечание, что слишком уж много цветов у меня в игре. В текстовых режимах не было такого богатства оттенков. Дело в том, что я реализовал полноэкранный lightmap, просчитывающий какое угодно количество источников освещения. При этом, цвет каждого символа 24-битный (16 777 216 различных цветов). Иногда картинка выглядит пестро.
Для эмуляции ретро цветовых режимов я сделал семь дополнительных опций: три монохромных режима, два 16-цветовых режима (DOS/Mac), 2-битный и режим Game Boy. Также доступен режим LED шрифта. В таком режиме каждый пиксель каждого символа отделен от соседних. На видео ниже демонстрируются все режимы — как они влияют на картинку.
Алгоритм преобразования цвета для монохромных режимов сделал такой. Сначала рассчитываю яркость цвета (R, G, B):
V = 0,3 * R + 0,59 * G + 0,11 * B
Монохромные ретро-мониторы имеют разные цветовые тона для различной яркости символа. Поэтому оттенок также должен изменяться. Использую такую линейную интерполяцию:
RR = sqrt(V) * (monoR1 * (1 — V) + monoR2 * V)
GG = sqrt(V) * (monoG1 * (1 — V) + monoG2 * V)
BB = sqrt(V) * (monoB1 * (1 — V) + monoB2 * V)
Окончательный цвет (RR, GG, BB)
Для 16-цветовых режимов я использую другой алгоритм. Для каждого цвета (R, G, B) ищу ближайший цвет в палитре. Вот и все.
2-битный и режим Game Boy имеет только четыре цвета в палитре. Простой поиск ближайшего цвета дает очень темную картину. Поэтому прежде, чем искать цвет в палитре, я делаю нормализацию:
d = 1 / max (R, G, B)
normR = d * R, normG = d * G, normB = d * B
Формулы схематичные. Проверки на деление на ноль не стал упоминать. Надеюсь, что каждый кто решит поиграть в ASCIIDENT сможет подобрать для себя цветовую схему, которая максимально будет греть его или ее ретро душу.
6. Консоль с честным текстовым режимом
В процессе создания игры пришла идея поместить в игровой мир компьютерные терминалы с честным текстовым режимом. К ним можно подойти, подключиться и поработать/поиграть.
Если сама игра стилизована под текстовый режим 80x25 с плавным скроллингом и параллаксом текстовых слоев, то экран встроенных терминалов имеет разрешение 72x20 символов без всякой возможности выйти за пределы этой сетки.
Все приложения для встроенных терминалов (включая загрузчик) написаны на языке программирования DUHASM. Этот язык похож на Ассемблер, но имеет динамические переменные и массивы. Вот, например, кусок кода игры Pi-astre Hanter:
Забавная особенность — циклы реализованы в рамках условных конструкций, где вместо END ставится LOOP.
В момент запуска игра подгружает приложения из *.duhasm файлов и компилирует их в байт код. Когда игрок активирует консоль, то запускается честный интерпретатор.
На данный момент я написал две игры на DUHASM, которые уже доступны в текущей версии. Есть план написать редактор кода (тоже на DUHASM конечно), чтобы каждый игрок мог попробовать создать приложение/игру, которую увидят все другие игроки.
Надеюсь, что я не зря потратил много усилий и времени для реализации этой фичи и найдутся люди, которым понравится. Язык DUHASM безусловно требует доработки. Мне не очень нравится, как, например, происходит вызов функций с аргументами. По истории игры язык DUHASM придумал полу-разумный киборг, сбежавший из лаборатории космических пиратов. Удивительным образом этот язык программирования прижился на окраинах обитаемой части вселенной.
ЗАКЛЮЧЕНИЕ
Что ж, компромиссов набралось немало — набор символов, субсимвольная точность, анимация, цвета. Но и для сохранения чувства аутентичности текстовому режиму я предпринял немало за эти более чем два года разработки. Чтобы получать больше обратной связи и понимать, в правильную ли сторону я двигаюсь, решил запустить игру на раннем доступе в Стиме. Есть что-то магически привлекательное в текстовых режимах. Когда любую картинку можно набрать символами на клавиатуре, то сложно иногда удержаться и не запустить игру со встроенным ASCII редактором, да и не нарисовать прототип новой мини-игры, которую потом и реализовать на языке DUHASM.
Всем спасибо! Пока!
nanshakov
Вы офигенны!