Компонент - это основа нашего движка. Компонент представляет из себя базовую частичку функциональности объекта, каждый игровой объект это агрегация компонент и связи между ними. Например компонент Drawer - может инкапсулировать в себя функциональность рисования игрового объекта. Компонент Position - хранить позицию. У каждого компонента есть так называемые атрибуты - инициализационные данные и параметры - это другие компоненты которые ему нужны для работы. Описание класса с одним компонентом будет выглядеть вот так:
class SimpleComponentExample { component Position posComponet { position = Vector3(0,0,0); }; };
“Position” - тип компонента, “posComponet” его имя. Имя необходимо что бы передавать компонент в качестве параметра другому компоненту. Дальше идет секция описания атрибутов компонента или его инициализационных данных. Атрибуту с именем “position” присваевается значения Vector3(0,0,0). Атрибуты у компонентов строго типизированные, а список и их типы надо получать из описания компонентов, которое будет делать при их создании, наверно где-нибудь здесь.
Передача компонента ввиде параметра выглядит вот так:
class SimpleComponentParamExample { component Position posComponet { position = Vector3(0,0,0); }; component Drawer draw(Position = posComponent); };
Здесь используется сокращенный вариант объявления компонента, без описания его атрибутов, когда у компонентов нет атрибутов - можно использовать такую запись. В описании компонента как бы две секции описания: его параметров и его атрибутов, в зависимости от типа компонентов любой их них может не быть, вплоть до вот такого:
class SimpleComponentParamExample { component Simple s; };
Но если компонент требует описания параметров и атрибутов - то при попытки обработки такого скрипта будет ошибка. Итак для передаче параметра используются круглые скобки, в них через запятую пишется имя параметра и имя компоенета, думаю в большинстве случаев компоненты в качестве параметров будут принимать не больше одного компонента какого-то типа, поэтому чаще всего имя параметра будет совпадать с типом параметра, но не факт, ещё реальных тестов не было, а наша теория может оказаться просто теорией. Думаю походу разберемся и если что читайте новости :)
Передача параметров в переделах одного класса важна, но есть ещё более мощная возможность - передавать параметры от инстанса переданого в конструктор класса. Если брать не слишком оторваный пример из жизни когда это может понадобится том можно рассмотреть такую ситуацию, у нас есть класс с описанием какого-то абстрактного орудия, которому в конструктор приходит имя модели и инстанс прототипа снаряда, которыми орудие может стрелять. Выглядить этот класс будет примерно вот так:
class Gun { constructor(object projectile, string modelName); component Spawner sp { prototype = projectile; }; component GunMechanics mech(Spawner = sp); component Drawer draw { model = modelName; }; };
Класс состоит из трех компонент: “sp” -компонент типа “Spawner” - это компонент котый отвественнен за порождение объектов из прототипа, который задается атрибутом “prototype”, “mech” - компонент механики орудия(“GunMechanics”), с ним будет взаимодействовать объект который будет управлять орудием, грубо говоря этот компонент инкапсулирует в себе всю механику стрельбы и использует “sp” для порождения снарядов и наконец draw - это компонент отвественный за отрисовку нашего орудия, ему передается в качестве атрибута имя модели.
Теперь представим что нам надо создать пулемет. У нас есть класс который описывает пулю, пусть он называется “Bullet”. Описание пулемета будет таким:
class MiniGun: Gun { constructor():Gun(bul, "minigunModel") { MinigunBullet bul(); }; };
Что мы сделали - мы создали класс MiniGun который полностью унаследовал все компоненты класса Gun, внутри него мы создали инстанс пули “MiniBullet bul();” и передали его качестве параметра в конструктор родительского класса, туда же мы передали название модели, после разверти скрипта в базовом классе Gun атрибуты projectile и modelName, примут значения: первый станет инстансом bul, второй будет “minigunModel”; Можно было бы и не наследоваться, а использовать компоновку двух инстансов, но в этом случае теряется возможность получить доступ к копонентам Gun, а нам ведь оттуда нужно получить механику орудия. Дальнейшее использование MiniGun может быть в описании робота:
class Robot { constructor() { MiniGun miniGun; }; component Position pos; component RobotMechanics mech(Position = pos, GunMechanics = miniGun.mech); component AI ai(mech); component Drawer draw { model = "robotModel" }; };
Вся соль данного примера заключается в
component RobotMechanics mech(Position = pos, GunMechanics = miniGun.mech);
Здесь создается компонент типа RobotMechanics который инкапсулирует в себе функциональность механики робота, в нем могут быть спрятаны функции для перемещения ведения огня и например радар, этот компонент передается AI - мозгам, которые и будут использовать их. Но робот не сам стреляет - он стреляет через орудие - которое мы создали и для осущетсвления выстрелов ему, в качестве параметра, необходима механика орудия “GunMechanics = miniGun.mech” этой строчкой мы её передаем. Сначала идет обращение к объекту по имени, потом через “.” идет обращение по имени к компоненту который мы хотим передать. Так же дочерние инстансы могут брать компоненты класса их порождающего, но этот пример я напишу позже :)