[Лог #7] Класс рисовальщика.

Темой этого лога станет рендер. Расскажу немного о том как я себе представляю виртуального художника и почему лучше реализовать интерфейс IRender и класс-реализацию CRenderOGL, наример.
80 28 752
0
14
9 лет назад
Отредактирован Kozinaka
0
По идее, если для отрисовки объекта не нужно хранить состояния переменных специфичных для отрисовки, то в игровом движке никаких забот о рендере и быть не должно. Просто есть набор игровых объектов, по которым пробегается отрисовщик и так или иначе решает вопросы рисования.
Если хранить состояние нужно, то придётся чуть-чуть испачкаться. В минимальном варианте игровой объект должен уметь прицепить к себе внешнюю ссылку и предоставлять её по требованию. Я бы назвал это IBindable (потому как слов IRenderable в игровом движке не должно быть). Пробегаясь по объектам отрисовщик приделывает к игровым объектам объекты отрисовки из параллельной иерархии. Если у игрового объекта уже ассоциирован объект отрисовки - тогда не трогать, если нет (значит только что создали его) - создать и прицепить.
Например:
Игровой объект - зомби, у него есть координата и направление движения. Объект его отрисовки хранит у себя номер текущей анимации ходьбы и при отрисовке выводит нужный спрайт с нужным углом поворота.
Теперь представляем пачку зомби на карте. Как только в отрисовщик приходит игровой объект "Зомби" без ассоциированного объекта отрисовки, к нему приделывается свежый объект отрисовки, начинающий считать кадры анимации. Зомбаков много, ои находятся в разных стадиях анимации, которые хранятся в ассоциированных с ними объектами отрисовки. Мы разделили логику (координата, направление движения) от представления (выбор спрайта, номер кадра анимации) ценой одной внешней ссылки в игровом объекте.
0
15
9 лет назад
0
Kozinaka:
Каюсь! ) Вообще хотел когда-то сделать как советуют - разбить всё т.е. всякие там IRenderable, IMovable и т.д. но как-то не пошло :(
0
14
9 лет назад
0
По слоям разбрасывается раньше, тут этого просто нет. DrawWorm просто рисует червя на текущем слое и вызывается ровно только раз, на скольких слоях есть объект Worm. А вся кухня по слоению, бантчингу и сортировке находится внутри метода DrawScene() до прохода по слоям и вызовов DrawXXX().
Я бы сделал почти аналогично, но ... наследование использовал и ... всё рисование ... в классах игровых объектов
В данном случае "почти", это перемешивание логики с представлением. Покайся, пока не поздно! :)
0
15
9 лет назад
0
Kozinaka:
Ооо, понятно ) Я бы сделал почти аналогично, но вот вместо switch обычно наследование использовал и по этой причине всё рисование было реализовано в конкретных классах игровых объектов.
А по слоям раскидывает функция, например, DrawWorm или слой задаётся раньше ?
0
14
9 лет назад
Отредактирован Kozinaka
0
Я правильно понял идею?
Почти. Идея такая:
pDrawer->DrawAll(); 
А внутри что-то типа такого:
pSceneDrawer->DrawScene();
pGuiDrawer->DrawGUI();
А внутри DrawScene() что-то такое:
DrawLandscape();

for(auto &obj : pGameEngine->Scene->Objects)
{
     switch(obj->Type)
     {
          ...  
          case Worm: DrawWorm(obj);
          ...
     }
}
0
15
9 лет назад
0
Kozinaka:
Хмм .. ну со слоями вроде понятно - без них в 2Д сложновато. Но есть вопрос - по сути рисование объектов как-то вот так делается ?
void SuperGame_MainLoop_Draw( )
{
    // ...
    // собственно pDrawer - это тот, кто всех рисует
    // DrawWorm - это рисование "червя"
    // pWorm - объект самого "червя"
    pDrawer->DrawWorm( pWorm );
    // ...
}
Я правильно понял идею ?
0
14
9 лет назад
Отредактирован Kozinaka
0
Жирный плюс за разделение логики объекта и его отображения.
Спасибо :) На самом деле можно разделять и с методом Draw, просто получается морока с двумя параллельными иерархиями объектов. Одна иерархия в игровом движке - это сугубо логика, а вторая иерархия уже с объектами отрисовки. Причём иерархии разные. Я в одном своём проекте так заморачивался, пользуясь возможностями C++ по множественному наследованию, но в текущем, "Несыти", не стал. Оставил только иерархию объектов в игровом движке + жирный класс отрисовщика, который всё про то, как рисовать игровые объекты знает.
А можешь небольшой примерчик кода как эта штука работает? С жирным отрисовщиком и конкретным объектом.
Кода дать не могу, окно треснет, а словами опишу. У меня движок спрайтовый, сцена слоёная. Например, есть слой с ландшафтом, есть слой с тенями наземных существ, есть слой с наземными существами, дальше тени высоких объектов, отбрасываемые на наземных существ и т.д. Некоторые объекты занимают несколько слоёв - у фонаря есть основание со своей тенью, спрайт света и верхняя часть. Внутри некоторых слоёв требуется сортировка спрайтов по тому или иному признаку - иногда просто по координате Y, иногда сложнее - звенья у червя, например, должны отрисовываться от хвоста к голове, чтобы наложения корректные были.
Имеем коллекцию объектов из игрового движка, которые нам нужно отрисовать в виде сцены. Есть полтора десятка слоёв - таких же коллекций объектов.
  1. В зависимости от типа объекта заталкиваем его в каждый слой, в котором он отрисовывается.
  2. Сортируем нужные слои нужным способом
  3. Отрисовываем слои последовательно снизу вверх, рисуя от объекта в слое только его соответствующую часть.
Этим всем занимается отрисовщик. Пока различных объектов и слоёв было немного, я всё разруливал на switch'ах, но, в итоге, пришел к пачке методов у отрисовщика типа DrawXXX(Layer layer), где XXX - имя объекта. Короче, к одному методу Draw я и пришел, только при отсутствии иерархии отрисовываемых объектов - методы отрисовки плавают в воздухе, а применяются к объектам из игрового движка, в которые отрисовка не вмешивается, это вообще другая сборка.
0
15
9 лет назад
0
... жирный клас отрисовщика, который их сортирует, группирует ...
Ну и RenderDevice можно аналогичной штуке научить ) Хотел вот добавить методы BeginScene \ EndScene (как в DirectX) там бы сбрасывались\ выводились списки на отрисовку.
А можешь небольшой примерчик кода как эта штука работает? С жирным отрисовщиком и конкретным объектом.
0
24
9 лет назад
Отредактирован prog
0
Kozinaka:
У меня, например, объекты сами себя рисовать не умеют. За них это делает жирный клас отрисовщика, который их сортирует, группирует, солит по вкусу и только потом рисует.
Жирный плюс за разделение логики объекта и его отображения.
2
14
9 лет назад
2
но думаю во всех самописных движках что-то вроде этого ))
Нет. У меня, например, объекты сами себя рисовать не умеют. За них это делает жирный клас отрисовщика, который их сортирует, группирует, солит по вкусу и только потом рисует. Но можно и с методом Draw у каждого. Каждый онанирует, как ему импонирует.