Добавлен механизм синхронизации асинхронной задачи с родительским потоком.
Метод Await() у класса AsyncTask
Добавлен механизм LoadOnDemand для StaticMesh ассета
При обращении к BulkData ассета, если задача на загрузку не запускалась или была сброшена, то ставит задачу на исполнение, и возвращает nullptr указатель, если задача не исполнена.
Добавлен механизм "Сброса" асинхронной задачи
Сбрасывает состояние задачи на Created, возвращает возможность вызова метода Run(), и, по необходимости, очищает связанные с задачей данные.
Исправлено удаление объекта из глобального тикера, в случае, если объект удален.
Небольшие новости по Linux сборке:
Посмотрел я на выходных еще раз в сторону SDL и GLFW, и, все-таки пришел к выводу, что придется писать все самостоятельно. Что SDL, что GLFW создает около 5-6 внутренних потоков на стадии инициализации (для обмена данными; чтения ввода, итд). Это автоматически ломает суть ThreadManager с его max_concurrent_tasks. В итоге буду писать сам. С Windows то все просто - там не так много кода, а вот с Linux придется посидеть. Посмотрел я, как работает Wayland, и мне, откровенно не понравилось. Нет, оно конечно очень гибко, но там даже для самого простого окна получается достаточно много кода. Есть, правда, libwaylandpp, который это дело упрощает... Посмотрю, может через него удастся.
Добавлены классы ThreadManager и AsyncTask (о них чуть ниже)
В RAT контейнер добавлена основная и дополнительная информация о геометрии (за исключением текстурных координат)
Добавлена асинхронная загрузка геометрических данных
Пока в экспериментальном режиме. Будет переписана в будущем с учетом Лодов, информации о которых в формате контейнера пока нет, а так-же пока сам ассет не знает в каком состоянии геом. данные.
Добавлена зависимость от glm
Добавлены правила сборки под оптимизацию glm под разные наборы инструкций (SSE, AVX, AVX2)
Т.к. зависимости добавляются через кастомные CMakeLists, то пришлось писать эти правила самостоятельно (но по большей части копипаст из оригинала)
Исправлена ошибка в парсе конфигов в случае, если конфиг, созданный в Windows парсится в Linux.
ThreadManager и AsyncTask
Теперь собственно об этих классах. Ранее я писал о том, что скорее всего придется реализовать шаблон пула потоков, но чуть подумав пришел к выводу, что более гибким решением будет использование его более простой реализации - Очередь потоков.
Как это работает. ThreadManager при старте запрашивает систему о том, сколько параллельных задач может выполнить система (это можно переопределить через параметр max_concurrent_tasks в Engine.ini с возможностью перевыставить этот параметр в "пользовательском" конфиге), с ограничением, что если этот параметр больше полученного от системы значения, то движок уйдет в исключение (думаю понятно, зачем это сделано). Так-же в этом классе хранится очередь задач AsyncTask и производных от них.
Каждый AsyncTask является отдельным потоком. Его нельзя запустить произвольно - только поставить в очередь на исполнение. ThreadManager в каждом тике основного потока опрашивает очередь и смотрит в каком состоянии находится задача. Если состояние Pending и если текущее кол-во запущенных задач меньше, чем max_concurrent_tasks, то запускает ее. Если задача закончила выполнение, то убирает ее из очереди и запускает следующую. Если очередь пуста, то Тик для ThreadManager отключается, тем самым дополнительно экономя ресурсы основного потока.
Таким образом, мы всегда можем быть уверены, что при использовании этого механизма у нас будет задействовано оптимальное для конкретной системы кол-во потоков. Исключение в этом случае есть - это пресловутые E-ядра (или малые ядра, если хотите). Пока не знаю, что с ними делать, т.к. неначем тестировать. Сложность в том, что при запуске задачи мы не можем быть уверены, на каком ядре система запустит эту задачу (на большом или малом). Иными словами, если задача, которая рассчитана на запуск на полноценном ядре запустится на малом, то будет просадка производительности, с которой мы ничего не сможем сделать.
Так-же пока не придуман механизм "синхронизации" потоков и механизм блокировки данных, чтобы избежать случайного обращения к ним, пока они гоняются в потоке. Это в процессе.
Добавлен Класс Assets/StaticMesh для хранения статичных мешей
В AssetManager добавлена автозагрузка заголовков ассета при старте движка
Разработан формат заголовка для Статичных мешей
Второй заголовок после форматного 0x52415401
Сейчас активно идет работа над непосредственно представлением данных в RAT контейнере (а также смотрю, что нам там в принципе нужно. Ноды, объекты-пустышки (dummy), и прочее)
А так-же потихоньку думаю как это дело загрузить. Т.к. мной была выбрана парадигма "Загрузить по требованию" (Load On Demand), то логично, чтобы загрузка была асинхронной. Т.е. пора вводить в движок потоки. Чтобы иметь более интуитивный контроль над ними, скорее всего нужно будет реализовать паттерн ThreadPool (пул потоков) и очередь тасков для работы с ними. Это вот план на ближайшую неделю/две, думаю.
Израильская оборонно-технологическая компания готовится открыть в Уганде свой первый игровой парк с платформой на основе очков метавселенной.
Симуляция обучения Combatica: Combatica
Израильский стартап в сфере оборонных технологий Combatica , основанный четыре года назад, зарекомендовал себя как ведущий бренд в области симуляций военной подготовки. В то же время, сектор безопасности всё чаще обращается к двойному назначению – военному и гражданскому. Недавно Combatica переосмыслила концепцию двойного назначения, открыв свой первый игровой парк в Бусике, Уганда.
В ближайшие месяцы в США откроется парк, аналогичный угандийскому, а в Европе планируется ввести в эксплуатацию в первом квартале 2026 года. Аналогичный объект планируется построить и в Израиле. Потенциал в США также велик из-за разнообразия вооружений и необходимости доступной и удобной возможности обучения, не обязательно на боевых полигонах.
Welcome to Combatica
Combatica используется для обучения боевых подразделений с использованием передовых возможностей искусственного интеллекта. Около полугода назад компания представила версию 2.0, которая включает более 50 сценариев, семь карт и даже режимы активации приборов ночного видения.
Combatica: Combatica
С тех пор система продвинулась до версии Combatica 2.1, которая включает улучшенную аналитику и данные, а также позволяет бойцам контролировать длительность реакции и получать подробную информацию о местах повреждений на противнике или внутри него.
Разнообразие возможностей, предоставляемых системой, в отличие от «сухих» армейских учений, способствует более эффективному обучению с использованием очков метавселенной (виртуальной реальности) и позволяет оператору вводить новые угрозы во время учений. Для эксплуатации системы в полевых условиях требуется всего два чемодана, что делает её практичной и удобной. За последние месяцы продажи растущей израильской компании утроились как в Израиле, так и за рубежом.
Тем временем консалтинговая компания Frost & Sullivan недавно признала Combatica лидером мирового рынка платформ тактической подготовки к 2025 году. Frost & Sullivan отметила, что Combatica выделяется своей способностью адаптировать стратегические инициативы к потребностям рынка.
RatTools - это минималистичная утилита, которая с помощью библиотек assimp, а в дальнейшем и других (freeimage, ffmpeg и др.), конвертирует различные внешние форматы (fbx/obj на данный момент) в контейнер RAT (Rellict AsseT), который понимает движок.
Вывод информации об объектах исходного файла перед перегоном их в RAT
Контейнер RAT
Контейнер RAT представляет собой бинарный файл, в котором в уже подготовленном для работы виде содержится необходимая информация.
Состоит из 4x байтового заголовка. MagicNumber определяющий то, что используется RAT формат, и AssetTypeID определяющий тип ассета (например, для Статичного Меша заголовок будет выглядеть как 0x52415401). Следующие байты содержат заголовок уже конкретного типа ассета и контейнер с данными. В "сыром" виде к формату НЕ применяются методы сжатия и шифрования.
Заголовок статичного меша в формате RAT
Статичный меш
Статичный меш - это простейший меш без анимаций, морфа и скелета. Т.е. это простейшая сетка. Однако она может содержать несколько самостоятельных объектов, или наборов материалов, которые следует учесть при работе в движке.
Иными словами, формат статичного меша может содержать, в том числе, сдвоенные/строенные вершины, а так-же несколько триангулированых "Фейс" сетов. А движок в свою очередь это должен оперативно загружать и использовать в корректном контексте (например при использовании 2х MaterialID [скриншот выше]) объект будет разделен на два и на отрисовку он будет отправлен как два разных объекта, но при этом он все равно должен остаться единой сущностью.
Сделать это можно несколькими методами. И сейчас я выбираю лучший. Задача - сделать так, чтобы между загрузкой асета в память и отправкой его на отрисовку прошло как можно меньше времени и тактов cpu. Самое простое решение - это хранить данные уже в оптимизированном виде с уже продублированными вершинами. В этом случае файл поднаберет в весе, но, если загружать данные большими блоками, то это даст неплохой буст в производительности. С другой, стороны, это добавит энтропии, когда мы будем добавлять поддержку анимации и скелетов (банально нужно будет привязывать к ключу/таргету/кости больше вершин). С третьей стороны, поле упаковки ассетов в RelictFS, будет применено сжатие и в принципе разница скорости при загрузке данных будет небольшой, если вообще будет. В общем - пока делаю так, а потом посмотрим, как это будет работать.
Демо моей игры готово, и в него уже можно поиграть в браузере. А про муки выбора движка можно прочитать в статье. Возможно, если вы ищете движок для своего игро-шедевра, мое мнение дилетанта окажется вам полезным.
Демо моей игры готово, и в него уже можно поиграть в браузере. А про муки выбора движка можно прочитать в статье. Возможно, если вы ищете движок для своего игро-шедевра, мое мнение дилетанта окажется вам полезным.
Как вообще я пришел к идее создания игры? Я рисую безбюджетный мультсериал “Хтонавты» - про антропоморфных животных, обитающих в абсурдном мире, где пост-советская реальность с гастрономами и гаражами переплетается с измерениями лавкрафтианского ужаса (а , может, не в таком уж и абсурдном, если посмотреть по сторонам). Более подробно можно почитать про мультик здесь же на PIKABU:
На днях мне удалось закончить демо платформера, действие которого происходит в той же вселенной. Доступен целый уровень, который можно пройти примерно за две минуты с небольшим за одного из главных персонажей – антропоморфную жабу, которая должна собирать бутылки и прыгать на голову обитателям спальных районов и порождениям древнего кошмара. В поисках таинственной руны Перерождения наш герой преодолевает путь, на котором его ждут как привычные нашему глазу хрущевки, электрички, трансформаторные будки и ларьки с шаурмой, так и жуткие существа из неведомых миров.
Когда встретил стража промозоны по пути в гастроном
Скажу сразу: от программирования я далек максимально. С концепцией о том, что чтобы правильно делать игры, надо страдать (иначе игра будет неправильная) ознакомлен. На лавры гениев от игроделания не претендую. Моей задачей было найти самый простой для меня движок и сделать самый простой платформер, чтобы, прежде всего, мне самому было в него весело играть. С этой задачей я справился, чему немало удивлен. И даже получил несколько хороших отзывов на разных ресурсах. Вот, например, очень приятный для меня отзыв от доброго человека с itch.io – спасибо ему, он в буквальном смысле выразил то впечатление от игры, к которому я стремился.
Конечно же, как любой человек, выросший на видеоиграх, я всегда мечтал создать свою игру. Мой опыт кодинга, если это можно так назвать, исчерпывался попытками изучения C+ (или, может быть, C++) в школьные годы. Тогда под руководством погромиста из некоего компьютерного кружка мне удалось накодить что-то вроде примитивного текстового квеста. На этом энтузиазм иссяк, я переключился на более увлекательные в раннем подростковом возрасте занятия, а рудиментарные знания о волшебном языке C канули в варпе.
При этом меня всегда привлекали редакторы уровней в играх. В свое время я чуть ли не сутками ваял уровни в Warcraft 2, HOMM 2 и 3, да и во всем, к чему был прикручен хоть какой-то редактор. Например, в древней гоночной игре Stunts, в которой пытался построить какое-то подобие города, чтобы кататься по нему на машине задолго до этих ваших Драйверов и GTA. Как не сложно догадаться, меня привлекало то самое «создание своих миров», которое толкнуло на скользкую дорожку игроделания уже не первую заблудшую душу.
Еще вспоминается игра Graal Online, которая представляла собой буквально копию третьей Зельды, но с открытым миром. К ней также был присобачен редактор уровней, да еще и с подобием скриптов. С помощью невероятных костылей в этом редакторе умельцы создавали почти что РПГ с квестами, сменой дня и ночи и другими фокусами. Кстати, пока писал этот текст, выяснил, что Graal Online все еще существует, имеет множество модификаций, и поиграть в него можно вот тут (у меня в браузере не запустился):
Следующая попытка научиться делать игры была предпринята во время пандемии. Вынужденно сидя дома, я решил, наконец, освоить увлекательный процесс игроделания. Попытка сделать клон Space Invaders на юнити успехом не увенчалась. Как выяснилось впоследствии, туториал на ютубе содержал ошибки, и автор заведомо втирал доверчивым слушателям какую-то дичь. В итоге что-то на экране ездило туда-сюда, но это было совершенно несопоставимо с объемом потраченного времени. Насколько я знаю, в юнити можно делать игры без кода, путем перетаскивания логических блоков, если я правильно это называю. Но до этого дело не дошло.
Все что угодно можно сделать лучше с помощью котов. Тем более - гигантских.
Позже я потыкал еще какой-то движок, название которого, вспомнить уже не получается. Он был попроще, написание кода было значительно минимизировано. На этот раз я попробовал сделать платформер, и что-то даже получилось, но содержало слишком большое количество критических косяков, логика исправления которых была мне совершенно непонятна.
Также был опробован старый добрый гейммейкер. Посмотрел туториалы и немного потыкал на чужом компе. Вероятно, этого недостаточно для адекватной оценки, но мне он показался неочевидным и несколько перегруженым, особенно на фоне того, как он подается в качестве простого и универсального движка.
Вернулся я к своей идее фикс сравнительно недавно, когда пара человек из армии подписчиков моего проекта (13 подписчиков на DTF, 8 на Пикабу, почти 200 в Телеге – это уже микроблоггер или макро?) откомментила, что неплохо было бы во вселенной моего мультика сделать игру, возможно что-то вроде визуальной новеллы. Так а я всегда за!
Поезд в Хтонск
Был даже установлен кримпай, он же - Ren'Py, но, вскоре пришло осознание, что визуальные новеллы меня привлекают больше в теории. Я в них никогда толком не играл, а с помощью ренпайя хотел сделать что-то вроде квестов в Космических Рейнджеров или книжек Choose Your Adventure (у меня были такие в детстве, и как-нибудь я напишу про них отдельный пост). В итоге эта идея была отложена до лучших времен в пользу старого доброго платформера. И тут включается старая песня о главном: в чем же его делать?
Первым делом мой взгляд упал на Construct, который привлек меня концепцией ультра-интуитивного и простого конструктора для игр. В какой-то очередной статье было написано, что он хорош для быстрого создания прототипов игр, чтобы впоследствии воплощать эти идеи на более солидных движках. Да мне бы хоть прототип создать, подумал я.
В видео-туториалах все выглядело привлекательно, но отпугнул несколько конский ценник на это развлечение. Не то чтобы я любил деньги так же сильно как мальчик Бобби из песни мультфильма Остров Сокровищ, но все же не всегда готов закидывать кровно заработанные дензнаки за то, что, возможно, мне и не пригодится. Есть ли что-то подобное, но подешевле? Как оказалось, есть!
Главное, чтобы инструкции были понятны и доступны
Это довольно давно существующий движок под названием Gdevelop. В отличие от сребролюбивого консракта, он условно бесплатный. Платная подписка добавляет такие безусловно удобные функции, как, например, возможность экспортировать проект чаще, чем раз в сутки. Но и без нее вполне можно слепить работающую игру.
При этом сам процесс игроделания прост до неприличия. Программировать не нужно. Нужно делать игру по сути в двух окнах. В первом рисуем уровни, добавляя туда игровые объекты. Объектам можно присваивать различные поведения (behaviors), которые в свою очередь можно настраивать, ставя галочки, где надо (и не ставя, где не надо). Например, не нужно прописывать руками, что при нажатии кнопки «влево», объект движется влево с такой-то скоростью и ускорением, и так для каждой клавиши управления – достаточно просто добавить объекту поведение «персонаж платформера» и он начинает автоматически управляться стрелками и пробелом. Но при большом желании, можно и прописать действия и их особенности для каждой клавиши. Простор открыт.
Во втором окошечке составляем из готовых блоков систему событий, основанную на соблюдении условий «если» и «тогда». К примеру: если объект «игрок» входит в коллизию с объектом «враг», отключается поведение «персонаж платформера», проигрывается анимация «смерть», проигрывается звук «смерть», выжидается 2 секунды (чтобы успела проиграть анимация), уровень перезагружается.
В целом, все понятно даже без туториалов, но последние могут сделать процесс обучения намного более стремительным и приблизить сладостный момент создания собственной игры. Какие-то вопросы вы научитесь решать сами, например, у меня получилось самостоятельно найти решение поблемы, когда после убийства врага, анимация его смерти продолжала убивать протагониста.
Как себя чувствую, когда решил проблему сам без туториалов
Отдельно хочется отметить простоту эскпорта и выкладывания игры на соотвествующие сайты. Я пока выложил только на itch.io, но сделать это получилось неожиданно просто и быстро. Я ожидал самых различных проблем, например, косяков с разрешением или тормозов. Но в итоге все залилось и отлично играется. Единственной проблемой оказалось то, что в Опере в игре нет звука, но, к примеру, в FireFox все работает. Правда, на реддите люди описывают определенные проблемы при экспорте, так что, возможно, у меня это ошибка выжившего.
Разумеется, не пытаюсь рекламировать сей движок, но так как с помощью него я, можно сказать, воплотил в жизнь, свою мечту и не заплатил за это ни копейки, считаю, что рассказать о нем другим пытливым умам будет справедливо.
В качестве минусов могу отметить, что в последние пару дней, программа мистическим образом пропадала с компа после его выключения или перезагрузки, и ее приходилось переустанавливать заново. Подозреваю, что это происходило из-за сбоев в автоматическом обновлении. Как только удалось установать обновление, чудо-движок исчезать перестал.
Уверен, что знающие люди, могут быстро рассказать, почему Gdevelop ни для чего не годится и делать игры надо, например, на Питоне (все, что я знаю про этот язык – его название). Но в моем случае Gdevelop отлично сработал и позволил добиться поставленной цели. Так что если вы хотите попробовать сделать свою игру – возможно, это лучший выбор, благодаря простоте и быстроте освоения. Не исключаю, что в будущем я перейду на другой движок, а, может, и не перейду.
Так или иначе – спасибо за чтение. И буду благодарен, если поиграете в мое демо и что-нибудь напишите!
Для SystemFS добавлена возможность задать корень через DefaultEngine.ini
Добавлен функционал сбора "индексов" файлов в файловой системе
Добавлен функционал опознавания файла как ассета
Добавлен функционал регистрации конкретного ассета в AssetManager с привязкой к конкретному RelictClass объекту
Эта штука будет нужна для механизма "умной" загрузки/выгрузки ассета в/из памяти, и если заработает как надо, то этот-же метод будет применен при работе со скриптовыми объектами.
В общем случае, сейчас все сводится к тому, что каждый Asset в движке будет иметь свой экземпляр, производный от интерфейса IAsset в памяти, связанный с конкретным файлом. В нем уже будет находится контейнер с самим ассетом, но подгружаться с диска он будет только тогда, когда это будет необходимо. И выгрузит только тогда, когда пользоваться им никто не будет (все это без прямого участия конечного программиста).