Чтобы блог не пустовал, решил с вами начать разработку движка.
Шутка. Я точно не знаю какая точка с запятой застряла во мне, но решил начать писать собственный движок на С++
Да не просто движок, а с особой системой представления классов - смесь унаследованной (ООП) и компонентной (ECS)
Про ООП (Объектно-ориентированное программирование):
Про ECS (Entity-Component-System - Сущность-Компонент-Система):
И скажу честно - сейчас в том же Портал Солвере реализована небольшой набросок система-компонент, когда я писал лазеры
В общем сложив А + Б, выходит что ООП и ECS хороши по своему, а учитывая постоянную константную МнеНечегоДелать, то можно попробовать так вообще написать свой движок. Поэтому представляю вам!
Root Engine
Движок, написанный на смешанности ECS и ООП. Да, я знаю - это безумно. В принципе еще никто особо не реализовывал это (Все говорят про минусы ООП в отличии от ECS, а никто не думал соединить их?)
Скажу сразу: Это чисто базовый эксперимент. У меня нет желания соревноваться с Unity, Unreal Engine, Godot и тд. Да, структура кода будет напоминать Unreal Engine - мне так привычней, как программисту на UE. Синтаксис интуитивно понятен и привычен
Немного про наш с вами план:
- Для начала напишем логику отображения окна и отделим логику от движка, чтобы в любой момент мы могли переписать модуль отображения окна и ничего не слетело
- Затем рааспишем структуру всего движка (рендера, математика и тд. - в дальнейшем расскажу)
- И самое главное... Рефлексия - это инструмент, который анализирует пользовательский код и разбивает его в понятный для движка код (раздрабливает) и загружает его в редактор (не перезапуская и не перекомпиируя сам движок). По сути этим можно назвать UHT - Unreal Header Tool, что генерирует файлы с вашим классом, но понятный для движка и затем движок применяет эти изменения. А вы думали откуда движок понимает, что такое UCLASS, UPROPERTY, UENUM и тд? :D (Интересный факт - почти у всех современных языков программирования С#, Java, Python и тд. - есть свои полностью реализованные под капотом инструменты рефлекси, А С++ увы... Будем учиться писать)
Вот такие пироги, считайте это наш 0-й день!
#RootEngine #PortalSolver
Шутка. Я точно не знаю какая точка с запятой застряла во мне, но решил начать писать собственный движок на С++
Да не просто движок, а с особой системой представления классов - смесь унаследованной (ООП) и компонентной (ECS)
Про ООП (Объектно-ориентированное программирование):
В ООП классы представляют как цепочку, унаследование. Например:
- Объект -> Сущность -> Компонент Сцены -> Пешка -> Игрок (логика игрока)
Или:
- Объект -> Сущность -> Компонент Сцены -> Пешка -> Зомби (логика зомби)
Но... Если я хочу, чтобы игрок был с логикой зомби? Тут уже начинается проблема ООП программирования, именуемой "Алмаз Смерти". Класс можно унаследовать только от 1 родителя, без пересечений. То есть я не могу просто соединить Игрока и Зомби
(А еще вставлю свои 5 копеек - тот же "Актор" в области Unreal Engine имеет много лишнего из-за слишком большой цепочки унаследования, что усложняет структуру движка и в будущем может убить оптимизацию)
Про ECS (Entity-Component-System - Сущность-Компонент-Система):
В ECS все представлено 3-мя основными понятиями - Сущность, Компонент и Система
В двух словах:
- Сущность хранит в себе набор Компонентов
- Компоненты хранят в себе только нужные им данные (координаты для компонента перемещения, скорость для комопнента физики и тд.)
- Система лишь имеет ссылки на эти компоненты и только просчитывает всю логику внутри
И естетсвенно это решает проблему "Алмаза Смерти", ибо теперь игрока, зомби и зомби-игрока можно собрать из компонентов, а всю логику прописать в единственном центральном блоке (системе)
Но от такого подхода может пострадать структура движка, ведь тот же UI - зачем мне в нем компоненты? Когда надо обычное унаследование:
Главное меню -> Настройки -> Настройки графики
И скажу честно - сейчас в том же Портал Солвере реализована небольшой набросок система-компонент, когда я писал лазеры
По началу я объединил логику лазеров в 1 класс, но тут произошел конфликт - лазерные кубики унаследованы от общего класса кубиков, и поэтому я не могу его унаследовать еще и класса с лазерами, поэтому.... Написал компонент для лазерных объектов + подсистему для обработки лазеров
В принципе это можно считать чем-то ECS, не учитывая что это больше как костыль, чем решение
(А один мой знакомый на Юнити так вообще написал 15+ компонентов и систем в 1-м игроке!! Емае, слава этому герою хвхвхв)
В общем сложив А + Б, выходит что ООП и ECS хороши по своему, а учитывая постоянную константную МнеНечегоДелать, то можно попробовать так вообще написать свой движок. Поэтому представляю вам!
Root Engine
Движок, написанный на смешанности ECS и ООП. Да, я знаю - это безумно. В принципе еще никто особо не реализовывал это (Все говорят про минусы ООП в отличии от ECS, а никто не думал соединить их?)
Скажу сразу: Это чисто базовый эксперимент. У меня нет желания соревноваться с Unity, Unreal Engine, Godot и тд. Да, структура кода будет напоминать Unreal Engine - мне так привычней, как программисту на UE. Синтаксис интуитивно понятен и привычен
Немного про наш с вами план:
- Для начала напишем логику отображения окна и отделим логику от движка, чтобы в любой момент мы могли переписать модуль отображения окна и ничего не слетело
- Затем рааспишем структуру всего движка (рендера, математика и тд. - в дальнейшем расскажу)
- И самое главное... Рефлексия - это инструмент, который анализирует пользовательский код и разбивает его в понятный для движка код (раздрабливает) и загружает его в редактор (не перезапуская и не перекомпиируя сам движок). По сути этим можно назвать UHT - Unreal Header Tool, что генерирует файлы с вашим классом, но понятный для движка и затем движок применяет эти изменения. А вы думали откуда движок понимает, что такое UCLASS, UPROPERTY, UENUM и тд? :D (Интересный факт - почти у всех современных языков программирования С#, Java, Python и тд. - есть свои полностью реализованные под капотом инструменты рефлекси, А С++ увы... Будем учиться писать)
Вот такие пироги, считайте это наш 0-й день!
#RootEngine #PortalSolver
❤4🔥2
Программисты на UE, подкормка для вас - примерный концепт кода в моем движке
Зачем нужны RCLASS(System)?
И да, как вы заметили - сущностей у меня нет -> Это не ECS, но и ООП назвать нельзя...
Поэтому представляю вам:
Hybrid Component Model (Гибридная Компонентная Модель)
(Авторское название хвхвхвхв)
Да, стиль и синтаксис очень сильно похоже на Анриловский. Но в отличии от него у меня будет очень хорошо развита связь компонент-система (И как вы заметили - из-за макросов RCLASS(System) и RCLASS(Component), я избегаю ООП'шного "Алмаза Смерти"
Зачем нужны RCLASS(System)?
В обычном варианте, когда система унаследована от базовой RSystem, все бы хорошо, но есть 1 нюанс - если я соединю 2 системы в одну, то в лучшем случае компилятор пошлет меня далеко да подальше, ибо обе системы унаследованы от базовой, и их соединение приведет к "Алмазу смерти". Так что чуть запарюсь, но сделаю создание систем интуитивно понятным (Многое засуну под движок, чтобы вам было легче 😭)
И да, как вы заметили - сущностей у меня нет -> Это не ECS, но и ООП назвать нельзя...
Поэтому представляю вам:
(Авторское название хвхвхвхв)
❤3🔥1
Интересно узнать ваше мнение. Компоненты и системы какую приставку будут иметь?
Anonymous Poll
86%
RMyComponent, RMySystem
14%
CMyComponent, SMySystem
Емае... Почаще бы мне так тратить время, но могу порадовать - с горью пополам установил ImGui и GLFW (С горью пополам конечно, но да ладно. Прошлый опыт с VS и 3D не пропьешь хвхвхвх)
Также накинул базовые классы:
[RWidget] - Является простой единицой для UI элементов. Может унаследовать в себе элементы
[RWidgetWindow] - Является основой для UI элементов (холст)
[RButton] - Обыкновенная кнопка
[RWindow] - создает и обрабатывает окна. Внутри инициализирует GLFW и ImGui
Вот такие пироги. Самое главное наверное - что в любой момент я могу переписать любой модуль (например перейти с GLFW на SDL2), и ничего у меня не слетит
Кому интересно - вот структура движка. Все красиво упаковано и вообще шик и блеск
Также накинул базовые классы:
[RWidget] - Является простой единицой для UI элементов. Может унаследовать в себе элементы
[RWidgetWindow] - Является основой для UI элементов (холст)
[RButton] - Обыкновенная кнопка
[RWindow] - создает и обрабатывает окна. Внутри инициализирует GLFW и ImGui
Вот такие пироги. Самое главное наверное - что в любой момент я могу переписать любой модуль (например перейти с GLFW на SDL2), и ничего у меня не слетит
Кому интересно - вот структура движка. Все красиво упаковано и вообще шик и блеск
❤3❤🔥1🔥1
UHT... UHT... Unreal Header Tool... Что если я вам скажу, что я накатал его за 1 вечер?
Правильно - у тебя лично жизни вообще нет? Нет)
Root Header Tool - полностью открытый аналог Unreal Header Tool, работающий с редактором и генерирующий тот самый ".generated.h" код!
И что мы получаем? Та абсолютно все! GENERATED_BODY, RPROPERY, RFUNCTION, RCLASS и многое-многое другое! А самое наверное крутое - Super:: - такая маленькая штучка, которая имеет ссылку на родительский класс. Я ее тоже реализовал
Теперь код все больше похож на Анриловский, а моим достижением можно считать привязку RHT к Rider'у (Кстати привязка к VS у них разная, но принцип один и тот же)
И да, первый прототип написан на Питоне, но мне уже ничего не мешает переписать его на С++ и скомпилировать в .exe файл, но займусь как-нибудь.. попозже. Сейчас и этого достаточно
В общем вы рассматривайте этот шедевр по кусочкам, а я пойду отпраздную хвхвххв
Правильно - у тебя лично жизни вообще нет? Нет)
Root Header Tool - полностью открытый аналог Unreal Header Tool, работающий с редактором и генерирующий тот самый ".generated.h" код!
И что мы получаем? Та абсолютно все! GENERATED_BODY, RPROPERY, RFUNCTION, RCLASS и многое-многое другое! А самое наверное крутое - Super:: - такая маленькая штучка, которая имеет ссылку на родительский класс. Я ее тоже реализовал
Теперь код все больше похож на Анриловский, а моим достижением можно считать привязку RHT к Rider'у (Кстати привязка к VS у них разная, но принцип один и тот же)
И да, первый прототип написан на Питоне, но мне уже ничего не мешает переписать его на С++ и скомпилировать в .exe файл, но займусь как-нибудь.. попозже. Сейчас и этого достаточно
В общем вы рассматривайте этот шедевр по кусочкам, а я пойду отпраздную хвхвххв
🎉3❤1🔥1
Наука рулит, сэр! Матеша
В общем хоть что-то закончено за день. Накинуты большинство типов данных, а также приступил к написанию RMesh, RRenderPipeline и тд.
Прогресс? Спокойная музыка, полный багаж матеши (Матрицы самое 💀) и попытка поболтать с OpenGL. Ему то GLAD подавай, то GLFW ему не нравится, то еще что-то... жесть просто
В общем хоть что-то закончено за день. Накинуты большинство типов данных, а также приступил к написанию RMesh, RRenderPipeline и тд.
Прогресс? Спокойная музыка, полный багаж матеши (Матрицы самое 💀) и попытка поболтать с OpenGL. Ему то GLAD подавай, то GLFW ему не нравится, то еще что-то... жесть просто
❤🔥4🤔1💋1
С++ и его небольшой "грязный" хак
Вызов функции из ничего =)
Пишите чтобы вы такое положили до запуска движка 👀
Не волнуйтесь, статьей на всех хватит
Вызов функции из ничего =)
static bool _AutoRegister - Это статическая локальная переменная, инициализация которой происходит один раз при загрузке программы (перед началом main())
Вроде бы - и что с этого? Но именно в static переменную можно подложить свой код и он выполнится еще до загрузки всей программы! Хвхвхвххв, небольшой грязный трюк, но работает же)
Пишите чтобы вы такое положили до запуска движка 👀
❤5🔥2
𝐑𝐨𝐨𝐭𝐓𝐨𝐨𝐥 𝐁𝐥𝐨𝐠
Чтобы блог не пустовал, решил с вами начать разработку движка. Шутка. Я точно не знаю какая точка с запятой застряла во мне, но решил начать писать собственный движок на С++ Да не просто движок, а с особой системой представления классов - смесь унаследованной…
Я говорил, что реализую создание систем без унаследования? Я сделал
Системы помечаются как RCLASS(System)
А затем на стадии компиляции регистрируются в движке (с небольшим хаком компилятора, а кому сейчас жить легко? хвхвхвх)
Я обещал - я сделал
Да, конечно сегодня планы были написать World и настроить камеру (чтобы камера хранила лишь основные данные, а дальше все камеры прогонялись через Render Pipeline, считайте система-компонент)
Но потерпел, завтра еще допишу регистрацию компонентов и.... Бинго! ГКМ будет написана и тогда можно будет реализовать все оставшиеся вещи
Напишу RObject - стандартный объект движка, RWorldObject - объект, который будет спавниться в мире (может еще подумаю над названием)
А позиции, физика, коллизия, рендер модели и камеры? Все будет компонентно и обрабатываться системами. От чего тот же RWorldObject может просто лежать в мире, или же иметь позицию
В общем ладно, день был необычным, всем спокойной ночи
Системы помечаются как RCLASS(System)
А затем на стадии компиляции регистрируются в движке (с небольшим хаком компилятора, а кому сейчас жить легко? хвхвхвх)
Я обещал - я сделал
Да, конечно сегодня планы были написать World и настроить камеру (чтобы камера хранила лишь основные данные, а дальше все камеры прогонялись через Render Pipeline, считайте система-компонент)
Но потерпел, завтра еще допишу регистрацию компонентов и.... Бинго! ГКМ будет написана и тогда можно будет реализовать все оставшиеся вещи
Напишу RObject - стандартный объект движка, RWorldObject - объект, который будет спавниться в мире (может еще подумаю над названием)
А позиции, физика, коллизия, рендер модели и камеры? Все будет компонентно и обрабатываться системами. От чего тот же RWorldObject может просто лежать в мире, или же иметь позицию
В общем ладно, день был необычным, всем спокойной ночи
👍5⚡1🤝1