Нашел 100 котов? А как насчет найти 101 думера? Или как я сделал подобную казуалку на Unreal Engine

Однажды и до меня дошла шумиха про эти гиперказуалки с поиском котов, что я решил сделать пародию с тем же геймплеем. Тем более 1 апреля скоро! Но, в отличии от игр с поиском животных, тут игрокам придется искать думеров! И не 100, а целых 101.

Как бы высоко ты не летал, не забывай где ты ползал
Как бы высоко ты не летал, не забывай где ты ползал

Идея сеттинга не заставила себя долго ждать, это были панельки с тоской. Арт нарисовался быстро, за день и ночь непрерывной работы я получил 8к изображение городка. Саундтрек попросил написать дружочка. А вот к движку подход был более осмысленным. Для такой игры нужна технологичность и современность, поэтому выбор сразу пал на unreal engine.

И это не шутка! Ведь в анриле есть прекрасные редакторы как материалов, так и виджетов (UI). Да и потому что забавно звучит, что такую игру делали на этом движке (:

Чел стоит и грустит, зачем он это делает?
Чел стоит и грустит, зачем он это делает?
Птитса - Думер обыкновенный
Птитса - Думер обыкновенный

А теперь техническая часть (как вы это любите)

Создание материала в анриле позволило оптимизировать игру. Идея заключалась в том, чтобы использовать всего 1 канал для каждой картинки, чтобы уменьшить размер игры и скорость загрузки текстур в память.

Выставляем компрессию на Alpha
Выставляем компрессию на Alpha

Выставив компрессию Alpha, мы сказали движку: "Брат, эта текстура используется как маска, брат. Поэтому отруби зеленый, синий и альфа каналы и перенаправь этот высвободившийся пул в более качественное отображение текстуры. Таким образом, мы получили не только меньше искажений на текстуре, но и избавились от альфа канала, получив в 2 раза меньше занимаего места текстурой!

Еще один параметр в текстуре.
Еще один параметр в текстуре.

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

Дино завричь
Дино завричь

Что насчет самих изображений? (внимние на картинку выше) Белый цвет используется для контура(значение 1), серый для заливки (значение 0.5), а черный — это будет прозрачность (значение 0). Как я смог эту лабуду отделить друг от друга? А вот смотри ниже!

Произвели отделение контура или типа того.
Произвели отделение контура или типа того.

Сначала вычитаем 0.5, чтобы где был белый стал серый, а где серый стал черный. Далее умножем это минимум на 2, чтобы серый обратно стал белым, а черный не стал никем (0 на любое число будет 0). При этом, стоит заметить, что использовалась нода Saturate, что бы все наши значения всегда были от 0 до 1.

Используем полученный выше контур
Используем полученный выше контур

Берем полученный контур, добавляем контраста и используем его в ноде Lerp как Альфу. Зачем? А чтобы мы могли программно выбрать отдельно цвета для контура и для заливки без загрузки новых картинок!

Отделили прозрачность
Отделили прозрачность

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

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

Сравнение до и после
Сравнение до и после

Далее в голову пришла реализация идеи Темной темы. Я создал значение в material parameter collection (Что-то типа глобальных значений для материалов).

Окно Material Parameter Collection
Окно Material Parameter Collection
вот так вот инвертируем
вот так вот инвертируем

Как видно выше, реализация проще некуда. Я просто инвертирую цвет пикселей у исходной картинки, ведь она черно-белая! И, так как я делаю инстансы этого материала и вставляю в них все текстуры элементов интерфейса, то все они инвертируются автоматически, благодаря всего одному значению из Material parameter collection! Чистая халява

Сравнение Темной и светлой тем
Сравнение Темной и светлой тем

Далее дело за малым — расставить кликаемые объекты и сделать управление.

Управление получилось сделать быстро:
Кручение колесика меняет зум со смещением виджета относительно положения курсора на экране.
Перемещение это добавление дельты движения курсора к текущему положению виджета.
И не забываем в итоге клампить все значения, чтобы как при скейле, так и при перемещении, мы не могли выйти за пределы нашей картинки!

Хочу подметить, что при вычислении зума и перемещения я не вставляю эти значения напрямую в виджет, а исполюзую их как target для Finterp To в тике. Таким образом все смещения становятся очень плавными и приятными

Лёрпим анимации всем двором
Лёрпим анимации всем двором

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

Image Size Не подхватился, жесть
Image Size Не подхватился, жесть

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

Хитроумный код
Хитроумный код

В итоге я еще прикрутил кол-во оставшихся думеров, таймер прохождения в ms и лидерборды стима.

Отображение оставшихся объектов и таймер собственной персоной
Отображение оставшихся объектов и таймер собственной персоной

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

Используем Mod
Используем Mod

Релиз в Steam

Сама игра будет бесплатной и выйдет 1 Апреля в стиме. Поддержать добавлением в желаемое и посмотреть мои другие игры можно тут:

Всем спасибо ^_^

2222
9 комментариев