El Dia de Muertos: отчет о разработке
Вкратце о разработке — мы договорились делать с художником, она подсказала крутую идею - день мертвых, офигенно же, дата важная и для живых и для мертвых.
Дальше из вариантов мне показался самым подходящим платформер. Хотя я никогда платформеров не делал и не так чтобы фанат жанра, но зато там по графону можно развернуться, да и вообще — надо пробовать новое.
Художнице сделала офигенного ГГ, но дальше пропала. Возможно учеба виновата, возможно не понравилось то в каком направлении я начал разработку, но в общем остальные ассеты видимо будут из инета.
По программной части вообще можно долго рассказывать, но кто это будет слушать? А хотя почему бы и не рассказать.
Язык — crystal. Никому не известная хрень, которая и винду то поддерживает экспериментально. Синтаксис как Ruby, но при этом статическая типизация и быстрый почти как С.
Основа игры — ECS. Технология созданная где-то в сумрачных недрах коммерческого геймдева. Ну я писал уже про нее. Начались мои приключения с того что я был удивлен — как так, нельзя добавлять одинаковые компоненты на одну сущность. Ни в leoECS нельзя, ни в аналогах. И в чатике ECS предлагают решения разной степени костыльности. И главное — нельзя несколько компонентов не потому что это как-то идеологии противоречит, а просто потому что усложняет библиотеку ECS. Мол много надо разных крайних случаев предусмотреть. Вызов принят, все равно я свою библиотеку ecs делаю, пусть будут множественные компоненты. А еще сделал компоненты которые существую один фрейм и удаляются как только исполнение возвращается к системе которая их создала. И где-то с этого момента начались непонятные падения. Порча памяти, какая-то хрень происходит, добавишь одну систему всё ломается, уберешь — вроде всё ок.
Ну проблема знакомая, надо удалять детали по одной пока не останется голый костяк на котором ошибка сохраняется. В конце концов и до бага доберешься. Но тут так не работало. Удаляешь «лишнее» — ошибка пропадает. Возвращаешь и удаляешь другое — тоже пропадает. На простых тестах вообще не ловится.
Пропустим моменты отчаяния и тоски, когда я рассматривал переход на юнити или взятие другой библиотеки ECS. Мне пришло в голову что виноват гц и я выкинул его заменив на свою заглушку (которая просто выделяла память но не удаляла). И это даже какое-то время помогало. Так вот, пропустив все эти метания — я поменял несколько фич и даже нашел несколько портящих память багов.
Но базовой проблемы это не решило — после определенной сложности программа падает на винде если скомпилирована в дебаге а не в релизе. Я не знаю кто тут виноват. Возможно я. Возможно компилятор Crystal. Одно радует — если компилировать в режиме «release» всё работает. Вот только время компиляции в release быстро растёт со сложностью программы и на данный момент составляет 40 секунд. Это тоже одна из особенностей Crystal — из-за его волшебного вывода типов он не способен на инкрементальную компиляцию. Обычно это не беда, ведь в дебаге всё компилируется быстро, но теперь ждать 40 секунд каждый раз чтобы посмотреть хорошо ли ходит монстр или прыгает игрок стало невыносимо. Я попробовал выпиливать фичи, чтобы урезать время компиляции, но это путь в никуда. Ииии новая идея — это же на винде проблемы, да? На линуксе у Crystal дела намного лучше, может даже и нормальный стектрейс ошибки выведет и я пойму почему на винде в дебаге падает. Осталась одна мелочь — если выкинуть графон то ошибка не воспроизводится. Значит надо поставить линукс и портировать мой движок на него. А да, я забыл, кроме crystal и myecs у игры есть и третий стремный компонент — мой движок, nonoengine. Написан на паскале, основан на SDL. До недавнего времени работал только на винде.
Ну ок, я какое-то время назад пробовал добиться чтоб в виртуалке работал opengl и пришел к выводу что у vmware с этим дела лучше чем у остальных. Правда manjaro на котором я остановился в тот раз при запуске предложил обновиться, нашел кучу конфликтов пакетов, ну и перестал грузиться в графическом режиме, ну и фиг с ним, мне сейчас не нужен bleeding edge linux hardcore. Взял дистрибутив минта который валялся скачанным, поставил на виртуалку, обнаружил что разрешение экрана не меняется, загуглил, о чудо, есть понятный способ какие галочки поставить, в общем заработало. OpenGL Mesa 3.3, пойдет. В процессе портирования движка проблем почти не было — поменять все слеши на обратные, да отключить SDL_GL_MULTISAMPLESAMPLES (если его использовать, то на витруалке тебе просто не дают контекст GL) и SDL_GL_SetSwapInterval (который тоже почему-то на виртуалке падает). Ну и соответственно скостылить свой «VSync», потому что я лох и у меня вся логика привязана к частоте обновления.
После этого о чудо — движок и игра завелись на линуксе и работают в дебаге. И ошибки никакой не возникает, что косвенно говорит о том что виноват crystal. Правда из-за тормозов виртуалки компиляция занимает секунд 15, но 15 это все-таки не 40. Так что игра возможно будет поддерживать линукс (правда установка будет тем еще адом, или квест по сборке из исходников тысячи проектов (crystal, chipmunk, lazarus, и это только начало) или я закину все библиотеки в дистрибутив и возможно заведется на убунте\минте 19).
Ну и раз уж я разошелся, еще несколько букв по геймдизайну.
Я решил делать платформер с а — физикой, б — генерацией уровней. По первой части — ну я уже нагуглил что это так себе идея и лучше было делать кастомную обработку игрока чем возиться с настройкой движка, но зато как прикольно игрок перебирает лапками когда прыгает с разгона на площадку и ему надо затормозиться. В целом прыжки более-менее управляемы (ну или это я приноровился), но хардкорные любители платформеров конечно сразу дропнут. А, и коллайдеры кривые, из-за этого игрок может цепляться за углы и это жутко бесит. Возможно в релизу станет чуть лучше, но не факт.
Генерация — я решил сделать как в spelunky только лучше. Долой квадратно-гнездовую расстановку шаблонов, долой спуск вниз как основу геймплея. Что я, с опытом рогаликов лучше не сделаю?Работает это примерно так — есть набор шаблонов, у каждого отмечены входы и выходы, мы ставим один в случайное место на большой карте и стыкуем к его выходам другие (а к ним дальше третьи и так пока есть куда впихнуть шаблон). Повторяем и повторяем, ну а оставшееся место заполняем шумом.
Ннну, в теории казалось прикольно, на практике всё работает, но генерится скучная лапша. Надеюсь, дело в малом числе шаблонов. В конце концов, нужны же фичи, на одних лифтах и ходячих туда-сюда скелетах логично что получается скучновато.
Ну и короче видео того что пока есть:
- 19 ноября 2021, 17:50
- 09
Вопросы программистов:
По видео, не привычно видеть как персонаж низко по платформе ходит, даже по сравнению с NPC. Выглядит интересно. Удачи! =)
Сущность - это ведь контейнер компонентов. А почему бы его не сделать более функциональным и сделать в нём список (или массив) из компонентов. Соответствующие методы добавления, удаления по типу, получения списка всех компонентов указанного типа. Так получиться легче манипулировать компонентами будет, работать не с типами, а просто с классами. (это просто размышления, надо на практике проверять)
Как ты решил данный вопрос?
я решил что для большинства компонентов это действительно не нужно. Поэтому те для которых нужно - помечаются специальной аннотацией. А дальше они хранятся также как и обычные компоненты, просто мы не проверяем что нельзя добавить больше одного.
Насчет массива - у меня были идеи добавить в ecs функции по работе с множественными компонентами как с массивом - получать список, удалять и т.д. Но как это оптимально реализовать я не уверен. В итоге сейчас их можно только
Наверное, если появится задача где нужно с ними более сложно работать - буду думать.
В чатике еще рекомендовали вместо множественных компонентов сделать прикрепление сущности к сущности (иерархию сущностей). Хотя это параллельная задача, иерархии сущностей видимо так и так понадобятся если что-то более сложное делать.
Во flecs вообще и то и то есть - любой компонент это сущность, привязывай как хочешь что хочешь, создавай отношения, строй иерархии. Но я там немножко почитал - автор пытается ECS в какой-то монструозный боинг превратить, чтоб и вебсерверы и вообще всё на нем писать. Я лучше пока на велосипеде покатаюсь.
На тему ECS попадался материал, в котором предлагают еще дальше развивать эту концепцию - MECS.
да, тоже интересная идея. Но то что надо явно прописывать кто от чего зависит - неудобно (хотя может и норм). И то что циклическую зависимость нельзя создать - хотя сходу вариантов когда именно циклическая зависимость нужна я не вижу, но вполне возможно что они есть. Что-то типа: нанесение урона вызывает вырастание шипов, а вырастание шипов вызывает урон у противника. Если просто удалять в выбранной точке кадра, то проблемы нет - шипы удаляются после создания урона от шипов, а после удаления старых шипов создаются новые. Соответственно шипы от урона в этом кадре создадут урон в следующем. А если делать это сообщениями - то фиг, циклическая зависимость.
Насчёт 40 сек компиляции. У нас на работе гигантский проект, фронтенд которого компилится с typescript 1-2 мин. Но только в первый раз, потом при изменении файлов он их подтягивает за секунды. Интересно, есть ли подобный watching для компилируемых языков? Чтобы изменялся, например, только один объектный файл при сохранении, а не все.
Конечно. В TypeScript ты на каждый файл получаешь JavaScript, так и с компилируемыми языка. При компиляции на каждый файл исходного кода ты получаешь скомпилированный исходный файл (compilation unit), из которых потом уже происходит сборка программы, библиотеки (для C++ это из .cpp получаем .obj, а потом .exe, .dll, .lib, для Delphi это .pas - .dcu - .exe, .dll, .lib).
Походе для языка Crystal это именно проблема при работе на ОС Windows, которое может такого и не делать из-за ошибки или ещё что там...
Это называется инкрементальная компиляция. но у Crystal ее из-за некоторых особенностей языка (главным образом из-за глобального вывода типов) нет и в ближайшее время не предвидится.
Хотя если точнее, то в дебаге она в каком-то рудиментарном виде есть (при изменении одной строчки перекомпилируются не все модули а только половина), но хах, дебаг то под виндоуз и не работает.
Может, стоит увеличить минимальную длину платформы и высоту туннеля с 1 до 2 тайлов? А то даже пустой уровень уже пугает меня хардкорностью. :)
счас уже вряд ли что-то сильно поменяю, но да - получилось довольно хардкорно (а учитывая кривоватую физику точнее будет сказать "издевательски". Лол, из-за силы прыжка которая зависит от длительности нажатия я за время тестов уже начал опасаться за свою клавиатуру). Осталось за выходные сделать вступление, которое бы хоть чуть-чуть тронуло игрока и заставило его превозмогать.