мне одному кажется, или все эти флаги [[]], в перемешку с шаблонами <<>> и auto и лямбдами, породит легасикод, который потом в 2030ом году будет занозой в одном месте?
пример:
[[какие то флаги]]
template<typename T, шаблоно-магия>
T foo(T a, T b, std::function<bool(const T &)> comp)
[[какие то флаги]]
[[какие то флаги]]
{ ...какая то магия...
return comp(a, b);
}
[[какой то флаг]]
auto res = foo<TA, TB, TZ <TA::bo, TZ::a>>(arg1, arg2, [](const TA &a){ return a.isValid();});
Как говориться, не надо — не пользуйся, но это не отменяет того факта, что породиться код переполненный лямбдами, все возможными мета-обьектами на шаблонной магии. В перемешку с опционалами и флагами на каждом чихе и пуке.
Я бы на вашем месте, реализовывал это все методом конечного автомата с памятью.
Либо пошел интереснее и возможно построил бы граф или дерево из конечных автоматов.
Память наша — это не очередь а стек. И наше состояние и есть наша память, по которому генерируется последующее поведение. Возможно использовать несколько автоматов, один отвечает за состояние памяти, за состояние самой сущность «ожидает, идет, ищет, возвращается».
п.с.
Есть у меня мысль использовать один-два рекурентных слоя для нейронки. Такая нейронка легко пишется в принципе на любом языке, с двумя входами координат еды, и несколько входов о текущем местоположении и возможно состояний. И того 4+ входных данных.
На выходе должны получать выходной вектор направление, скорость и действие, которое сущность должна выполнить. Прошлое помним за счет рекурентных данных. Проблема только в том, что рекурентные сети я не умею обучать. Но тут в идеале, обучение с подкреплением подойдет. Да и для большого количества ботов, допустима большая погрешность. Пусть она даже будет свыше 30%. По этому ее глубокой и сложной делать не надо даже. вход -декодирующий слой — рекурентный слой — кодирующий слой — выход.
Ну… а что такого интересного в это генерации? Может ТС поделиться деталями реализации?
А то, то что описано — это простейший паттерн билдера. А реализация мало чем отличается от реализации смежных рас в DwarfFortress (типо птицелюды, человеко-медведи, ящеро-кто-то там)
Честно скажу, больше похоже на рекламу, где все описание выше — это всего лишь предлог для публикации.
Если топить за генерацию что описано выше — это не расы. Рас там мало, все остальное — это лишь национальности или подтипы этих рас.
Если пойти по примеру дварфортресса и взять идею генерации фоготенбистов, то можно сделать реальную генерацию рас и их подтипов. Достаточно отбросить понятие «базовая раса». Т.е. выбросить всех эльфов, гномов, дворфов и прочее.
Ввести базовый тип «Гуманойдный», «членестоноги», «головоногий» и т.д.
Дальше генерирввать рассовые параметры. Например:
Размер
Разброс размера
Интеллект
Плоть/панцирь/т.д.
Цвет
Разброс цвета
Тип оболочки
Наличие шерсти
Наличие чешуи
Наличие глаз
и т.д.
Т.е. через билдер собирать более разношерстные расы. Имена же рас генерировать на основе каких то черт и их типа. Это будет более честно.
Можно ввести определенные климатические переменные, физические переменные и делать параметры меж связные. Например размер обратено пропорционален реакции/ловкости существа. Из за мировой гравитации существа с коэфицентом K не могут летать. Где K — это коэфицент площади существа, его веса и размера
А так… я в статье ничего интересного не увидел. С тем же успехом, я мог бы написать статью про то, как я реализовал гибкие триггеры и телепорты в своей игре. Или реализовал липкую-физику.
Вообще, многие работодатели любят CV, что бы оно было не больше 1-2 страниц. Кратенько, красиво оформлено. Пункт «О себе» и достижения. Особенно запад любит. Я как сделал себе CV и выложил на LinkedIn, мне активно стали писать из Европы.
Для РФ же и HR-роботов сделал объемное резюме, шаблонное.
Совету вверху, подкупят, если резюме смотрит работодатель.
Но если резюме смотрят HRы, у которых все стоит на поток — они его выбросят, ибо им нужен блок «Скилы», и опыт работы. И им плевать, что вы по ночам ловите НЛО, а днем, нарежаетесь в человека паука.
просто надо изучить популярные паттерны в геймдеве.
Их акторсистем, это та же самая ECS с ерархией.
Советую взять более лайтовый движок, чисто для изучения популярных архитектур. Освоив идею граф-сцены и компонентов, переходить на такие монстры как UE4 и Unity становиться на уровень легче. Но для UE4 лучше еще изучить паттерн Акторов, который он так же использует.
Но честно скажу, в Ue4 для 2D сильно перегруженно. У UE4 2D, это как у cocos2d-x 3D.
У первого 2D не удобен для индти. У второго функционал очень скуден и документация страдает для 3D.
Разработчик скорее всего затянул за движком тонну сервисов и не нужных модулей.
Обычно перед выпуском, после прототипирования, создают либо шаблон экспорта, либо пересборку нужных модулей движка. Скорее всего, данный фрукт просто подключил библиотеки System, Scurity из net core и всякие веб и аналитические сервисы.
Я не юзаю юнити. Но на годоте том же. Чистый движок без спрайтов весит 2мб, если использовать свой шаблон. А если использовать стандартный шаблон — чистый движок весит 15-20мб на андройде ( в зависимости от типа сборки и отладочной инфы)
Так же он разанлокал фпс, из за чего, батарея летит в хлам
Моей комментарий скорее направлен людям в комментариях, которые не смогли освоить тот или иной движок. Выше там кто-то жаловался, что UE4 ужасен, не удобен. И что мол, своей велосепед понятен.
Все движки имеют схожий принцип…
По поводу тому, что они решили.
Например. Физика…
В начале ты создаешь банальный перебор мешей и трасировку лучей.
Потом, когда их много — делаешь quad_tree/cube_tree с чанками. Дабы уменьшить перебор.
Потом все это дело отлаживаешь… отлаживаешь… очень долго отлаживаешь… несомненно, лучше взять хотя бы box2d.
Физика — первое решение
Интерполяция параметров. Для создания плавных анимаций и прочего. Например ни одним своим велосипедом мне не удалось превзойти гибкость того же godot, в котором ты абсолютно что угодно можешь заанимировать или размазать во времени.
Система сигналов/ивентов — часто, создавая свой движок, для создания слабой связности, реализация этой подсистемы заставляет переписать логику раза три-четыре.
Ерархия обьектов — можно пойти по классической ECS. Но часто, нужна группировка сущностей. Наследование родительских координат и т.д. Из за этого, ты опять же вынужден пересматривать по несколько раз свою архитектуру, если пишешь велосипед. Использовать GraphScene, ECS или гибридный двух этих паттернов? Или god object (антипаттерн) создать на подобии того, что есть в Unity?
Графическая подсистема. Dx, OpenGL, GL ES, Vulkan…
В итоге, я пришел к тому, что что-бы я не делал. Всегда есть что-то уже готовые и на уровень практичнее.
Даже такая мелочь как viweport, для адаптации разрешения под любой формат — реализация этого — не такой уж и простой шаг…
Костная анимация спрайтов, дерево анимаций, машины состояний.
До тех пор, пока ты придерживаешься базового концепта своей игры — свой велосипед будет не плох. Но как только начнешь реализовывать фичи. Именно фичи и новые игромеханики — начнется тонная проблем и бесконечный цикл переписывания движка. И за место того, что бы делать игру — ты будешь делать движок. А когда изучишь все эти аспекты, из чего строиться движок и какие паттерны — поймешь, что все ты изобрел очередной клон какого нибудь. MonoGame + Nez, Wolf engine, Ascid, Cocos2d-x, и т.д
Опыт конечно не сомненный, но время потрачено просто чудовищно.
Даже не смотря на то, что многие говорят «В своем движке ты можешь делать все что угодно» — это отчасти лож. В голове ты все не удержишь, а связность различных систем движка, рано или поздно встанут тебе боком и ты начнешь много и част перепсывать. А если ты успеешь что-то создать на нем — то сохранение совместимости со старым проектом — обойдется тебе боком. А если документировать все и обращаться к документации постоянно — это мало чем будет отличаться, от постоянного обращения к документации того же unity.
зря конечно так категорично к движкам. Ибо когда речь идет об физике, анимации, интерполяции свойств и прочего — ты начинаешь такие лютые велосипеды изобретать. Что в итоге весь твой компайл-тайм движок превращается в рантаймого франкенштейна.
А потом ты еще свои скрипты начинаешь интегрировать. Что бы ускорить разработку. Начинаешь редакторы карт изобретать, генераторы сценариев и прочее…
А если еще и кросплатформенным его делаешь — ух… AdMob, FireBase куча всяких сервисов…
А так есть такие кросплатформенные движки как Wolf Engine, Ascid, Godot, cocos2d-x. Бинарник чистого движка весит 2-5 мб. Не такая большая плата за 100500 готовых велосипедов. (у godot надо правда свой прекомпилированный шаблон создать, для такого веса)
Все свои проекты я перевел из велосипедов на движки.
А у Unity разве нету нативной реализации какого нибудь аналога сигналов и групп как в Godot например, мне казалось в UE4 и Unity давно уже изобретен велосепед, со слабо связаностью сигналов или observe паттерна?
В Godot ты можешь просто вызвать connect между сигналом источника и методом таргета обьекта.
Если же надо обратиться к группе обьектов, или выполнит бродкаст, то один вызов get_group_nodes(«Group») выдаст тебе список всех обьектов, а значит можно либо напрямую обратиться, либо создать какой нибудь event brodcast, который ловит сигналы, и по ним рассылает бродкасты определенной группе.
События кстати какие то примитивные, с привязкой к enum. Почему бы не сделать какой нибудь handler, принимающий правила и пусть он сам по себе и является событием.
Функция и будет обработчиком, которая определит правило поведения.
Но если идти дальше. То пусть event будет обьектом. В нем пусть хранится ссылка на источник и набор правил. Тогда мы автоматически отвязываемся от типов ивентов
Почему бы внутри обьектов не создать компонент, который накапливает полученные события.
А уже компонент, в свой цикл вызова Update/Tick/etc… обрабатывает все накопленные ивенты.
Если идти дальше. Еще и подсчитывать прошедшее время, что бы остановит обработку, если она затянется.
Обработчик событий должен только, и только отправлять/принимать события, не больше. Сами события пусть обрабатывают уже обьекты в свое время выполнения. Что бы не вызывать всеобщи фриз, когда у нас 100500 обьектов, которые друг другу кастят события
Я как раз таки хорошо умею делать велосипеды и быстро разбираюсь в новых либах.
Но как то решил попробовать с С++ пересесть на С#. С ним я и до этого работал, но в основном с .Net core.
Тут предложили на одну фирму поработать. В итоге им все эти фундаментальные знания, знания алгоритмов и прочее — нафиг не нужно. Им нужно на зубок знать весь .Net винды.
ASP .Net, Entity Framework, MVVM, MFP, MVC и т.д.
А когда я говорил, что писал асинхронные сервера на .net core на сокетах, писал врапперы во круг собственных сишных либ — они смотрели как на иродиевого.
Ни о каких хэштаблицах, деревьев, сортировок, обход графа, алгоритмов поиска, методов оптимизации и прочего речи и близко не было.
я хз, откуда взялась армия программистов… Но с какими студиями я не говорил, почти везде на одного программиста, 3-5 дизайнеров/художников приходится и зачастую все упирается как раз таки в художников.
Ну и как программист. Все таки писать тот подход, что предлагает автор, начнет рушиться, как только нужно будет создавать логику. На каждую новую сущность — писать логику взаимодействия между всеми остальными сущностями. Писать логику между компонентами не выйдет, т.к. компоненты не знаю об существовании сущности, т.к. у них нету общего базового класса. В итоге количество кода начнет расти в геометрической погрешности, с ростом разнообразных сущностей.
А теперь главный вопрос. Мне как гейм-разработчику, как пользоваться ECS, которую предлагает автор статьи?
Я вот слабо представляю, как это должно работать…
Например у меня есть компонент Renderable (от которой наследуются Mesh, Material, Texture и т.д.). У меня есть компонент Transform.
Есть RenderSystem, который вызывеат Draw всех спрайтов сцены.
Если у сущности нету компонента Transform, то Renderable рисуется так как есть, в нулевой матрице трансформации. Но если у сущности есть компонент Transform, то с матрицей трансформации Renderable должна складываться матрица трансформации Transform.
В итоге, во круг Transform у нас завязаны все другие компоненты. BoundBox, CollisionBox, Renderable и т.д. Можно всем этим компоентам задать свои параметры позиционирования, сделать методы и удалить компонент Transform. Но не много ли кода получается, ради трансформации одной сущности?
Еще пример. Вот допустим, у меня есть сущность.
Мне нужно в эту сущность, в рантайме добавлять новые компоненты, в зависимости от того, что с сущнностью происходит во время процесса игры.
Например это сущность Mechanism.
Я добавляю в него компонент Wheel, MechBody, Engine — в итоге я имею автомобиль.
Но я добавляю во время игры в него компонент Cannon и Trailer — и машина становиться боевой фурой. Я удаляю Wheel и добавляю компонент MechLegs — и фура с пушкой превращается в мехо-дредноут.
Если делать как говорит автор статьи, то мне придется наплодить 100500 разных сущностей, разных типов в коде.
Ну вот зачем мне отдельный класс Ork, Demon, Human, Barrel и Dragon?
Так я добавлю пару компонентов и при взаимодействиях игрока с одной из этой сущностью, могу сделать проверку на наличие того или иного компонента. А так мне придется писать 100500 перегруженных функций на каждый тип Enemy, с которым игрок будет взаимодействовать. Да и в итоге без проверки на тип — не обойтись.
Вот допустим игрок кидает фаербол по области. Я получаю список всех HitBox компонентов, которые попали в зону действия фаербола. Что делать дальше? Если классический подход, я могу напрямую получить parent компонента и отправить туда ивент или напрямую вызвать метод нужного мне компонента, если он есть.
В случае если у нас архитектура как у автора статьи — то что тогда делать? Это может быть как и Barrel, который вообще статичен и просто коллизия в мире так и Demon, который должен лечиться от огня.
Нарушая принципы OOD, и теряя пару процентов производительности, я оставляю понятный код и легко смогу крутить компоентами как вздумается, прикрутить к ним любую систему и т.д.
UE4 все же компонентный (Actor component). И Юнити тоже юзает компоненты, как мне известно. Компоненты не могут существовать без родителя. У годота — может, потому что это не компоненты, а узлы). В godot можно целые ветки сцен менять как вздумается на ходу. Я сам не так давно открыл его для себя, и довольно впечатлен. Простой, легкий, а мощный какой… Ничего лишнего нет.
Его собственный скриптовый язык не плох, строгая типизация, синтаксис питона, но упрощенный.
Ну и надо не забывать, что можно писать на C и C++ нативные модули. (Это как в UE4. Ты можешь блюпринты использовать, а можешь код писать)
Я не так давно на него перешел с cocos2d-x. Лично на кокосе я заколебался для простых вещей писать полотна текста на плюсах. Так еще и баги движка закрывать, который оказываются «Фичами». (например у FastTMX отрисовка тайлов не правильная при перемещении сцены, а не узла).
Но у того же годота нету поведенческого дерева (behavioral tree) из коробки. Нету визуального редактора шейдеров. И т.д.
Для меня это то что надо, гибки инструмент с минимальными наворотами для создания простых 2D игр.
Хочется упомянуть «Узловую систему» Node System.
Когда каждая сущность — это и узел и компонент, знающий об своем родителе и своих детях.
Древовидная структура. И каждый дочерний узел перемещается в родительских координатах, если они есть.
Сейчас наверное самый яркий показатель этой идеологи это Godot движок. Там все — это узлы, а любой узел — это еще и сцена. Упомянул бы cocos2d, но там не все гладко с реализацией.
пример:
Как говориться, не надо — не пользуйся, но это не отменяет того факта, что породиться код переполненный лямбдами, все возможными мета-обьектами на шаблонной магии. В перемешку с опционалами и флагами на каждом чихе и пуке.
Либо пошел интереснее и возможно построил бы граф или дерево из конечных автоматов.
Память наша — это не очередь а стек. И наше состояние и есть наша память, по которому генерируется последующее поведение. Возможно использовать несколько автоматов, один отвечает за состояние памяти, за состояние самой сущность «ожидает, идет, ищет, возвращается».
п.с.
Есть у меня мысль использовать один-два рекурентных слоя для нейронки. Такая нейронка легко пишется в принципе на любом языке, с двумя входами координат еды, и несколько входов о текущем местоположении и возможно состояний. И того 4+ входных данных.
На выходе должны получать выходной вектор направление, скорость и действие, которое сущность должна выполнить. Прошлое помним за счет рекурентных данных. Проблема только в том, что рекурентные сети я не умею обучать. Но тут в идеале, обучение с подкреплением подойдет. Да и для большого количества ботов, допустима большая погрешность. Пусть она даже будет свыше 30%. По этому ее глубокой и сложной делать не надо даже. вход -декодирующий слой — рекурентный слой — кодирующий слой — выход.
А то, то что описано — это простейший паттерн билдера. А реализация мало чем отличается от реализации смежных рас в DwarfFortress (типо птицелюды, человеко-медведи, ящеро-кто-то там)
Честно скажу, больше похоже на рекламу, где все описание выше — это всего лишь предлог для публикации.
Если топить за генерацию что описано выше — это не расы. Рас там мало, все остальное — это лишь национальности или подтипы этих рас.
Если пойти по примеру дварфортресса и взять идею генерации фоготенбистов, то можно сделать реальную генерацию рас и их подтипов. Достаточно отбросить понятие «базовая раса». Т.е. выбросить всех эльфов, гномов, дворфов и прочее.
Ввести базовый тип «Гуманойдный», «членестоноги», «головоногий» и т.д.
Дальше генерирввать рассовые параметры. Например:
Размер
Разброс размера
Интеллект
Плоть/панцирь/т.д.
Цвет
Разброс цвета
Тип оболочки
Наличие шерсти
Наличие чешуи
Наличие глаз
и т.д.
Т.е. через билдер собирать более разношерстные расы. Имена же рас генерировать на основе каких то черт и их типа. Это будет более честно.
Можно ввести определенные климатические переменные, физические переменные и делать параметры меж связные. Например размер обратено пропорционален реакции/ловкости существа. Из за мировой гравитации существа с коэфицентом K не могут летать. Где K — это коэфицент площади существа, его веса и размера
А так… я в статье ничего интересного не увидел. С тем же успехом, я мог бы написать статью про то, как я реализовал гибкие триггеры и телепорты в своей игре. Или реализовал липкую-физику.
Для РФ же и HR-роботов сделал объемное резюме, шаблонное.
Совету вверху, подкупят, если резюме смотрит работодатель.
Но если резюме смотрят HRы, у которых все стоит на поток — они его выбросят, ибо им нужен блок «Скилы», и опыт работы. И им плевать, что вы по ночам ловите НЛО, а днем, нарежаетесь в человека паука.
Их акторсистем, это та же самая ECS с ерархией.
Советую взять более лайтовый движок, чисто для изучения популярных архитектур. Освоив идею граф-сцены и компонентов, переходить на такие монстры как UE4 и Unity становиться на уровень легче. Но для UE4 лучше еще изучить паттерн Акторов, который он так же использует.
Но честно скажу, в Ue4 для 2D сильно перегруженно. У UE4 2D, это как у cocos2d-x 3D.
У первого 2D не удобен для индти. У второго функционал очень скуден и документация страдает для 3D.
Обычно перед выпуском, после прототипирования, создают либо шаблон экспорта, либо пересборку нужных модулей движка. Скорее всего, данный фрукт просто подключил библиотеки System, Scurity из net core и всякие веб и аналитические сервисы.
Я не юзаю юнити. Но на годоте том же. Чистый движок без спрайтов весит 2мб, если использовать свой шаблон. А если использовать стандартный шаблон — чистый движок весит 15-20мб на андройде ( в зависимости от типа сборки и отладочной инфы)
Так же он разанлокал фпс, из за чего, батарея летит в хлам
Все движки имеют схожий принцип…
По поводу тому, что они решили.
Например. Физика…
В начале ты создаешь банальный перебор мешей и трасировку лучей.
Потом, когда их много — делаешь quad_tree/cube_tree с чанками. Дабы уменьшить перебор.
Потом все это дело отлаживаешь… отлаживаешь… очень долго отлаживаешь… несомненно, лучше взять хотя бы box2d.
Физика — первое решение
Интерполяция параметров. Для создания плавных анимаций и прочего. Например ни одним своим велосипедом мне не удалось превзойти гибкость того же godot, в котором ты абсолютно что угодно можешь заанимировать или размазать во времени.
Система сигналов/ивентов — часто, создавая свой движок, для создания слабой связности, реализация этой подсистемы заставляет переписать логику раза три-четыре.
Ерархия обьектов — можно пойти по классической ECS. Но часто, нужна группировка сущностей. Наследование родительских координат и т.д. Из за этого, ты опять же вынужден пересматривать по несколько раз свою архитектуру, если пишешь велосипед. Использовать GraphScene, ECS или гибридный двух этих паттернов? Или god object (антипаттерн) создать на подобии того, что есть в Unity?
Графическая подсистема. Dx, OpenGL, GL ES, Vulkan…
В итоге, я пришел к тому, что что-бы я не делал. Всегда есть что-то уже готовые и на уровень практичнее.
Даже такая мелочь как viweport, для адаптации разрешения под любой формат — реализация этого — не такой уж и простой шаг…
Костная анимация спрайтов, дерево анимаций, машины состояний.
До тех пор, пока ты придерживаешься базового концепта своей игры — свой велосипед будет не плох. Но как только начнешь реализовывать фичи. Именно фичи и новые игромеханики — начнется тонная проблем и бесконечный цикл переписывания движка. И за место того, что бы делать игру — ты будешь делать движок. А когда изучишь все эти аспекты, из чего строиться движок и какие паттерны — поймешь, что все ты изобрел очередной клон какого нибудь. MonoGame + Nez, Wolf engine, Ascid, Cocos2d-x, и т.д
Опыт конечно не сомненный, но время потрачено просто чудовищно.
Даже не смотря на то, что многие говорят «В своем движке ты можешь делать все что угодно» — это отчасти лож. В голове ты все не удержишь, а связность различных систем движка, рано или поздно встанут тебе боком и ты начнешь много и част перепсывать. А если ты успеешь что-то создать на нем — то сохранение совместимости со старым проектом — обойдется тебе боком. А если документировать все и обращаться к документации постоянно — это мало чем будет отличаться, от постоянного обращения к документации того же unity.
А потом ты еще свои скрипты начинаешь интегрировать. Что бы ускорить разработку. Начинаешь редакторы карт изобретать, генераторы сценариев и прочее…
А если еще и кросплатформенным его делаешь — ух… AdMob, FireBase куча всяких сервисов…
А так есть такие кросплатформенные движки как Wolf Engine, Ascid, Godot, cocos2d-x. Бинарник чистого движка весит 2-5 мб. Не такая большая плата за 100500 готовых велосипедов. (у godot надо правда свой прекомпилированный шаблон создать, для такого веса)
Все свои проекты я перевел из велосипедов на движки.
В Godot ты можешь просто вызвать connect между сигналом источника и методом таргета обьекта.
Если же надо обратиться к группе обьектов, или выполнит бродкаст, то один вызов get_group_nodes(«Group») выдаст тебе список всех обьектов, а значит можно либо напрямую обратиться, либо создать какой нибудь event brodcast, который ловит сигналы, и по ним рассылает бродкасты определенной группе.
События кстати какие то примитивные, с привязкой к enum. Почему бы не сделать какой нибудь handler, принимающий правила и пусть он сам по себе и является событием.
Функция и будет обработчиком, которая определит правило поведения.
Но если идти дальше. То пусть event будет обьектом. В нем пусть хранится ссылка на источник и набор правил. Тогда мы автоматически отвязываемся от типов ивентов
Почему бы внутри обьектов не создать компонент, который накапливает полученные события.
А уже компонент, в свой цикл вызова Update/Tick/etc… обрабатывает все накопленные ивенты.
Если идти дальше. Еще и подсчитывать прошедшее время, что бы остановит обработку, если она затянется.
Обработчик событий должен только, и только отправлять/принимать события, не больше. Сами события пусть обрабатывают уже обьекты в свое время выполнения. Что бы не вызывать всеобщи фриз, когда у нас 100500 обьектов, которые друг другу кастят события
Я как раз таки хорошо умею делать велосипеды и быстро разбираюсь в новых либах.
Но как то решил попробовать с С++ пересесть на С#. С ним я и до этого работал, но в основном с .Net core.
Тут предложили на одну фирму поработать. В итоге им все эти фундаментальные знания, знания алгоритмов и прочее — нафиг не нужно. Им нужно на зубок знать весь .Net винды.
ASP .Net, Entity Framework, MVVM, MFP, MVC и т.д.
А когда я говорил, что писал асинхронные сервера на .net core на сокетах, писал врапперы во круг собственных сишных либ — они смотрели как на иродиевого.
Ни о каких хэштаблицах, деревьев, сортировок, обход графа, алгоритмов поиска, методов оптимизации и прочего речи и близко не было.
Киселев чего стоит. Такие речи загоняет, вся родня на него, как на святого молиться.
Ну и как программист. Все таки писать тот подход, что предлагает автор, начнет рушиться, как только нужно будет создавать логику. На каждую новую сущность — писать логику взаимодействия между всеми остальными сущностями. Писать логику между компонентами не выйдет, т.к. компоненты не знаю об существовании сущности, т.к. у них нету общего базового класса. В итоге количество кода начнет расти в геометрической погрешности, с ростом разнообразных сущностей.
Я вот слабо представляю, как это должно работать…
Например у меня есть компонент Renderable (от которой наследуются Mesh, Material, Texture и т.д.). У меня есть компонент Transform.
Есть RenderSystem, который вызывеат Draw всех спрайтов сцены.
Если у сущности нету компонента Transform, то Renderable рисуется так как есть, в нулевой матрице трансформации. Но если у сущности есть компонент Transform, то с матрицей трансформации Renderable должна складываться матрица трансформации Transform.
В итоге, во круг Transform у нас завязаны все другие компоненты. BoundBox, CollisionBox, Renderable и т.д. Можно всем этим компоентам задать свои параметры позиционирования, сделать методы и удалить компонент Transform. Но не много ли кода получается, ради трансформации одной сущности?
Еще пример. Вот допустим, у меня есть сущность.
Мне нужно в эту сущность, в рантайме добавлять новые компоненты, в зависимости от того, что с сущнностью происходит во время процесса игры.
Например это сущность Mechanism.
Я добавляю в него компонент Wheel, MechBody, Engine — в итоге я имею автомобиль.
Но я добавляю во время игры в него компонент Cannon и Trailer — и машина становиться боевой фурой. Я удаляю Wheel и добавляю компонент MechLegs — и фура с пушкой превращается в мехо-дредноут.
Если делать как говорит автор статьи, то мне придется наплодить 100500 разных сущностей, разных типов в коде.
Ну вот зачем мне отдельный класс Ork, Demon, Human, Barrel и Dragon?
Так я добавлю пару компонентов и при взаимодействиях игрока с одной из этой сущностью, могу сделать проверку на наличие того или иного компонента. А так мне придется писать 100500 перегруженных функций на каждый тип Enemy, с которым игрок будет взаимодействовать. Да и в итоге без проверки на тип — не обойтись.
Вот допустим игрок кидает фаербол по области. Я получаю список всех HitBox компонентов, которые попали в зону действия фаербола. Что делать дальше? Если классический подход, я могу напрямую получить parent компонента и отправить туда ивент или напрямую вызвать метод нужного мне компонента, если он есть.
В случае если у нас архитектура как у автора статьи — то что тогда делать? Это может быть как и Barrel, который вообще статичен и просто коллизия в мире так и Demon, который должен лечиться от огня.
Нарушая принципы OOD, и теряя пару процентов производительности, я оставляю понятный код и легко смогу крутить компоентами как вздумается, прикрутить к ним любую систему и т.д.
Его собственный скриптовый язык не плох, строгая типизация, синтаксис питона, но упрощенный.
Ну и надо не забывать, что можно писать на C и C++ нативные модули. (Это как в UE4. Ты можешь блюпринты использовать, а можешь код писать)
Я не так давно на него перешел с cocos2d-x. Лично на кокосе я заколебался для простых вещей писать полотна текста на плюсах. Так еще и баги движка закрывать, который оказываются «Фичами». (например у FastTMX отрисовка тайлов не правильная при перемещении сцены, а не узла).
Но у того же годота нету поведенческого дерева (behavioral tree) из коробки. Нету визуального редактора шейдеров. И т.д.
Для меня это то что надо, гибки инструмент с минимальными наворотами для создания простых 2D игр.
Когда каждая сущность — это и узел и компонент, знающий об своем родителе и своих детях.
Древовидная структура. И каждый дочерний узел перемещается в родительских координатах, если они есть.
Сейчас наверное самый яркий показатель этой идеологи это Godot движок. Там все — это узлы, а любой узел — это еще и сцена. Упомянул бы cocos2d, но там не все гладко с реализацией.