AvrDragon
> Вобще то нет.
это так какжется.
издатель всегда хочет игру не похожую на другие и тут как раз нужно то что не входит в твои 80% случаев.
Pushkoff
Такой базовый класс не накладывает сильных ограничений. Просто дает функционал. Если что нужно изменить можно в крайнем случае этот функционал не использовать. Больше чем уверен что 80% базовых классов подобных игр(shmup) выглядят примерно также, если не хуже.
nes
>Покажите свой базовый класс
Т.е. тот от которого возникают все мои потомки?
А зачем тебе?
Pushkoff
ну а лично твой опыт, сын ошибок трудных, что подсказывает ?
Pushkoff
ну конечно в коде кое где встрачаются конструкции на подобии
void OnCollision(GameObject go) { if(go is Ball || go is Whale) blablabla else if(go is StarGate) blablabla }
но если начнешь мудрить со всякой "компонентной архитектирой" сам этими компонентами по лбу и получишь. KISS
innuendo
> ну а лично твой опыт, сын ошибок трудных, что подсказывает ?
давным давно я писал казуалки, где у меня было типичное дерево наследования.
было время когда его хватало, но внезапно понадобились одинаковый функционал у разных ветвей дерева и ненужный в базовом классе и здравствуй копипаст
в домашней работе я это все вынес в отдельные функции, в основном это было взаимодействие объектов я его делал так же как тут написал кто-то только у меня оно называлось GameObject::OnAction( GameObject* other), сначала это была одна функция, но потом оказалось что некоторые объекты содержат эту же функцию практически в неизменном виде. так появилось OnAction( GameObject& , GameObject& ) которая уже не была членом GameObject, дальше я хотел применить Double Dispatch потому что начало функции решало какие конкретно объекты взаимодействуют, но уже было приятно что порядок взаимодействия был не важен.
потом Gameloft где опять он - жЫрнючий геймобжект, который с одной стороны мог все, но с другой стороны это все постоянно нужно было конкретизировать, ну и работать с объектом такого размера было очень неудобно, так как он умел все, от проигрывания анимаций до коллизий, и очень часто мы не знали какой функционал уже есть или уже не нужен часто его дублируя и забывая удалять ненужное (да нам и не давали на это время), и вот тут мы однажды собрали совещание чисто программистское, где была выдвинута идея это все разделить. причем делилось оно все на довольно простые компоненты в количестве около 7-10 штук, среди которых скрипт, коллизии, определение видимости врагов, позиция и привязка к полу, звук и тп, что очень упростило бы большинство гейм обжектов, которые к стати в большинстве своем были обычными дамиками со скриптом а иногда и без него (допустим позиция для спавна). мы попросили 2 недели, нам их не дали, но в свободное время (напомню что среднестатический рабочий день длился 12-14 часов) мы все таки разгребли часть этого говна и у нас упростились дамики. сразу скажу профит по памяти может и был но не такой большой как от урезания размеров текстур. по производительности не помню профита, возможно дамики остались в том же списке апдейта.
да к стати это тот же проект в котором бочка была по сути человеком, но без головы (в сетевой части нужно было отсеивать людей с головой от людей без головы ибо синхронизировать статические бочки было бы глупо)
ну в общем потом любые правки геймобжекта постоянно что-то портили, так как от него много чего зависело.
в общем из всего этого я сделал вывод что GoodObject это плохо, и простота егонаписания никак не зарешает сложность его поддержки.
я понимаю что сейчас начнутся крики что можно все делать аккуратно, но я вам скажу что нельзя, верней невозможно - любая ошибка заслуживает быть совершенной.
сейчас у нас проект с компонентной архитектурой но геймобжект тут есть и сам компонент фактически универсален, то есть геймобжект апдейтит свои компоненты.
мне больше нравится схема где компоненты апдейтятся своими менеджерами в строго определенном порядке и хранят зависимости от других компонент с которыми им нужно работать. такая архитектура более дружелюбна к многопроцессорности и геймобжект тут нужен только в момент инициализации компонент, дальше его можно хранить только для быстрого удаления компонент ему принадлежащих, что тоже не всегда нужно.
AvrDragon
> но если начнешь мудрить со всякой "компонентной архитектирой" сам этими
> компонентами по лбу и получишь. KISS
я не знаю сколько у тебя объектов в дереве наследования но когда их станет 7-10 система компонентов и станет тем что можно назвать KISS
dave
>А зачем тебе?
Выкрать гениальную идею и перепродать по дороже, очевидно же )
Хотелось бы посмотреть какие весчи люди выносят в базовый класс, может я чего не усмотрел.
Pushkoff
Вообще-то тема создавалась про базовый объект всех остальных объектов, а игровой объект это немножко другое имхо.
Планирую сделать в будущем что-то вроде такого:
class WorldObject : public IEntity { public: virtual GraphicsObject* graphicsObject(void) const; virtual void setGraphicsObject( GraphicsObject* object); virtual PhysicsObject* physicsObject( void) const; virtual void setPhysicsObject( PhysicsObject* object); virtual BehaviorObject* behaviorObject( void) const; virtual void setBehaviorObject( BehaviorObject* object); ... protected: // events virtual void onHit( void) = 0; virtual void onUse( Critter* user) = 0; ... };
Т.е базовый объект не содержит в себе каких-то игровых данных.
А вот игровой объект это практически некий контейнер для игровых компонентов (сами компоненты зависят от конкретной игры), также планируется что в нем будут реализованы
события игрового мира, например реакция на удар, на "использование" данного объекта (например НПС начинает говорить с игроком, книга открывается для чтения, контейнер открывается для просмотра содержимого и т.д).
TDataObject = class Template: TDataObject; Pic: TSym; Level: integer; ID, Desc: string; Name: TNounName; procedure ReadFromFile(INIF: TCustomIniFile; Section: string); virtual; procedure InitInternal; virtual; procedure AssignTemplate( aTemplate: TDataObject); virtual; constructor Create( aTemplate: TDataObject); function AddAsTemplate: Boolean; procedure RW; virtual; function Clone: TDataObject; procedure RW2; virtual; function NiceDescr: string; virtual; class procedure RegisterSelf; procedure Generate( ForLevel: integer; AddParam: Pointer); virtual; function AddToName: string; virtual; function GetName( Number: TGrammarNumber = It; aCase: TGrammarCase = Nominative; NeedColor: boolean = False): string; virtual; end;
Pushkoff
> GoodObject
правда плохо?
PlayerDark
> правда плохо?
очень плохо
nes
> Хотелось бы посмотреть какие весчи люди выносят в базовый класс, может я чего
> не усмотрел.
пост №2 практически гениален : )
struct IBase {};
у меня поначалу тоже при использовании ООП функциональность излишне стекалась к основанию иерархии
хорошо что в плюсах заложено много парадигм
например сериализация у меня сейчас выглядит очень просто, если кто-то унаследован от такого пустого IBase, я вызываю его метод, если нет, - то обычный memcpy () для POD
nes
Может не совсем по теме, но вспоминается эта книга: в ней графическое ядро наследуется от системного. А вот реализация базовых игровых объектов рассмотрена в 11-12 главах.
Тема в архиве.