ݺߣ

ݺߣShare a Scribd company logo
Михаил Казаков Старший программист, команда «Аллодов Онлайн»www.mail.ruМодульный объект: как это работает в Аллодах
Организация игровых объектовwww.mail.ru2???
Игровой объект с позиции ООПЖесткая иерархия объектовРазрабатывается на этапе планирования игрыЛегко поддерживаетсяЛогика внутри объектаЗависимости видны явноЕсли дизайн не менятьА если менять?www.mail.ru3
В конечном итогеClass UberObjectВесь код в одном классеНепонятно, где чья логикаКаша из зависимостейТрудно что-то добавитьНе доводите до такого{}Игровой объект с позиции ООПwww.mail.ru4class MyObject
Объекты в «Аллодах»www.mail.ru5EntityCreatureDeviceShipAvatarMob
Объекты в «Аллодах»www.mail.ru6EntityCreatureDeviceShipAvatarMobAstralMob
Объект «Астральный моб»www.mail.ru7Он же Ктулха
 Мозг
 Сотворение заклинаний
 Атака кораблей
 ПеремещениеОбъект «Обломки корабля»www.mail.ru8 Движение
 Стрельба
 Перевозка игроков
 Взаимодействие с ктулхами
 Подбор кораблямиМодульный объект АллодовОбщий контейнерХранит компоненты, предоставляющие интерфейсыОтображение интерфейсов в их компонентыИнтерфейс указывается явно при добавленииУмеет get() и put()Больше ничего не умеетИнтерфейс компонентСам по себе не умеет ничегоwww.mail.ru9
Модульный объект АллодовСоздание объектаBunch createMyObject() {final Bunch myObj = new Bunch();final Health health = new Health(100);myObj.addPart(Health.class, health);returnmyObj;}www.mail.ru10
Модульный объект АллодовПолучение определенной запчастиvoiddoSomething(@NotNull Bunch obj) {final Health health			= obj.getPart(Health.class);health.consume(30);}www.mail.ru11
Модульный объект АллодовНе спрашивайте, что это за объектСпросите, умеет ли он то, что вам нужно?if(myObjinstanceofMyClass) {		// Wrong way :(	}if(myObj.getPart(MyPart.class)!=null) {		// Right way :)	}www.mail.ru12
Объекты можно собирать «на лету»void assemble(@NotNullBunch myObj){myObj.addPart(Health.class, new Health(100));myObj.addPart(IFFOwner.class, newIFFOwner());	<...>}Таких функций может быть многоwww.mail.ru13
Знаем только про то, что нам нужноvoid affect(@NotNullBunch myObj){final Mortal mortal = myObj.getPart(Mortal.class);final Health health = myObj.getPart(Health.class);if(health.getLevel() < 50.f)		mortal.die();}Нет зависимостей на тип объектаНет зависимостей, полученных «в нагрузку»www.mail.ru14
Взаимодействия - между компонентамиɷɷ..15𳦳ٰ𳦳ٱʲٱʲٱʲٱʲٱʲٱʲٱʲ
void transform(@NotNullBunch myObj){myObj.removePart(CannonTargetInfo.class);myObj.removePart(ShipCollisionHandler.class);myObj.addPart(WreckCollisionHandler.class, new WreckCollisionhandler());}Можно заменять реализации интерфейсовМожно изменять поведение объектаwww.mail.ru16
voidmortalTest () {final Mortal mortal = new Mortal();Assert.assertFalse(mortal.isDead());	mortal.die();Assert.assertTrue(mortal.isDead());}Объект целиком создавать не обязательноМожно и более сложные функциональные тестыЛегко тестироватьwww.mail.ru17
Куда положить редко нужную логикуwww.mail.ru18ОбъектОбъектОбъектОбъектОбъектОбъектОбъектОбъект
Куда положить редко нужную логикуwww.mail.ru19ОбъектОбъектОбъектОбъектОбъектОбъектОбъектОбъектКакое-то событие
В стандартном подходеvoid someInternalProcessing() {	<...>	if(eventActive) doExtraLogic();	<...>}void itHappened(@NotNullMyObjobj) {obj.eventActive = true;	}Куда положить редко нужную логикуwww.mail.ru20
В модульном подходеclass ExtraLogicimplementsBunchPart {	void doExtraLogic() {		// Extra logic goes here	}}voiditHappened(@NotNullBunch obj) {obj.addPart(ExtraLogic.class, newExtraLogic());}Куда положить редко нужную логикуwww.mail.ru21
Пример использования «редкой логики»www.mail.ru22СканированиеОбновление позиции
Можно применять и для других целейwww.mail.ru23СервисКомпонентСервисКомпонентСервисКомпонент
Недостаткиɷɷ..24
void process(@NotNullBunch obj) {if(obj.getPart(RequiredPart.class) == null) {		// И что теперь делать?	}<...>}Например, заклинания, наносящие урон по площадиПодходит нам объект или нет?www.mail.ru25
void assebleObj(@NotNullBunch obj) {obj.addPart(Part1.class, new Part1());obj.addPart(Part2.class, new Part2());obj.addPart(Part3.class, new Part3());}Мы точно ничего не забыли?Эти запчасти между собой не конфликтуют?Заработает ли собранное?www.mail.ru26
В классическом подходеclass MyObj {@NotNullpublicMyPart part = newMyPart();}void process(@NotNullMyObjobj) {obj.part.doSomething();}Нет проверок @NotNullwww.mail.ru27
В модульном подходеBunch assembleMyObj() {final Bunch myObj = new Bunch();myObj.addPart(MyPart.class, newMyPart());returnmyObj;}void process(@NotNull Bunch obj) {finalMyPart part = obj.getPart(MyPart.class);if(part == null) return; /* Never happens */part.doSomething();}Нет проверок @NotNullwww.mail.ru28
<spell>	<targetImpacts>		<Item type = “ImpactKill” />	</targetImpacts></spell>Что нужно от цели воздействию ImpactKill?Нужно ли ему здоровье?А что будет, если его нет?В данных тоже есть проблемыwww.mail.ru29

More Related Content

Модульный объект: как это работает в «Аллодах Онлайн».