Нашел 100 котов? А как насчет найти 101 думера? Или как я сделал подобную казуалку на Unreal Engine
Однажды и до меня дошла шумиха про эти гиперказуалки с поиском котов, что я решил сделать пародию с тем же геймплеем. Тем более 1 апреля скоро! Но, в отличии от игр с поиском животных, тут игрокам придется искать думеров! И не 100, а целых 101.
Идея сеттинга не заставила себя долго ждать, это были панельки с тоской. Арт нарисовался быстро, за день и ночь непрерывной работы я получил 8к изображение городка. Саундтрек попросил написать дружочка. А вот к движку подход был более осмысленным. Для такой игры нужна технологичность и современность, поэтому выбор сразу пал на unreal engine.
И это не шутка! Ведь в анриле есть прекрасные редакторы как материалов, так и виджетов (UI). Да и потому что забавно звучит, что такую игру делали на этом движке (:
А теперь техническая часть (как вы это любите)
Создание материала в анриле позволило оптимизировать игру. Идея заключалась в том, чтобы использовать всего 1 канал для каждой картинки, чтобы уменьшить размер игры и скорость загрузки текстур в память.
Выставив компрессию Alpha, мы сказали движку: "Брат, эта текстура используется как маска, брат. Поэтому отруби зеленый, синий и альфа каналы и перенаправь этот высвободившийся пул в более качественное отображение текстуры. Таким образом, мы получили не только меньше искажений на текстуре, но и избавились от альфа канала, получив в 2 раза меньше занимаего места текстурой!
Уменьшаем фильтрацию с анизотропной до билинейной, чтобы уменьшить кол-во используемых семплов текстуры движком, тем самым уменьшив время рендера BasePass.
Что насчет самих изображений? (внимние на картинку выше) Белый цвет используется для контура(значение 1), серый для заливки (значение 0.5), а черный — это будет прозрачность (значение 0). Как я смог эту лабуду отделить друг от друга? А вот смотри ниже!
Сначала вычитаем 0.5, чтобы где был белый стал серый, а где серый стал черный. Далее умножем это минимум на 2, чтобы серый обратно стал белым, а черный не стал никем (0 на любое число будет 0). При этом, стоит заметить, что использовалась нода Saturate, что бы все наши значения всегда были от 0 до 1.
Берем полученный контур, добавляем контраста и используем его в ноде Lerp как Альфу. Зачем? А чтобы мы могли программно выбрать отдельно цвета для контура и для заливки без загрузки новых картинок!
Прозрачность отделили простым умножением на 2 и упомянутым выше сатурейтом. Таким образом серый тоже стал белым, а чернота не изменилась.
Хочу подметить, что так как мы используем материалы, а не голые текстуры, то и рендерятся они соответствующе — через пиксель шейдер. Благодаря этому, использовав в материале контраст на исходном изображении, которое используется как черно-белая «маска«, мы получаем ооочень четкую картинку и избавляемся от остаточных артефактов сжатия (видно на картинке »до» слева)
Далее в голову пришла реализация идеи Темной темы. Я создал значение в material parameter collection (Что-то типа глобальных значений для материалов).
Как видно выше, реализация проще некуда. Я просто инвертирую цвет пикселей у исходной картинки, ведь она черно-белая! И, так как я делаю инстансы этого материала и вставляю в них все текстуры элементов интерфейса, то все они инвертируются автоматически, благодаря всего одному значению из Material parameter collection! Чистая халява
Далее дело за малым — расставить кликаемые объекты и сделать управление.
Управление получилось сделать быстро:
Кручение колесика меняет зум со смещением виджета относительно положения курсора на экране.
Перемещение это добавление дельты движения курсора к текущему положению виджета.
И не забываем в итоге клампить все значения, чтобы как при скейле, так и при перемещении, мы не могли выйти за пределы нашей картинки!
Хочу подметить, что при вычислении зума и перемещения я не вставляю эти значения напрямую в виджет, а исполюзую их как target для Finterp To в тике. Таким образом все смещения становятся очень плавными и приятными
А вот расставить объекты оказалось на самом деле проблемой. Дело в том, что если мы вставляем в виджет не картинку, а материал, то скейл у него всегда дефолтный 32х32 и я не хотел вручную копировать разрешение текстур в виджет.
Но решение нашлось быстро - придумать костыль для автоматизации!
В виджете есть такой евент PreConstruct, который позволяет выполнять код прямо в эдиторе, в редакторе виджетов. Поэтому нодами вставляю в виджет картинку, чтобы она подхватила ее скейл, а после вставляю уже материал инстанс и скейл сохраняется, ура!
В итоге я еще прикрутил кол-во оставшихся думеров, таймер прохождения в ms и лидерборды стима.
Напоследок, хочу немного похвастаться вычислением отображения времени для таймера, а именно в применении Mod, чтобы отбросить остаток.
Релиз в Steam
Сама игра будет бесплатной и выйдет 1 Апреля в стиме. Поддержать добавлением в желаемое и посмотреть мои другие игры можно тут:
Всем спасибо ^_^