При создании игр вы часто создаете следующий игровой объект, от которого наследуются все сущности:
public class GameObject{
abstract void Update(...);
abstract void Draw(...);
}
Таким образом, в цикле обновления вы перебираете все игровые объекты и даете им возможность изменить состояние, а затем в следующем цикле прорисовки вы повторяете все игровые объекты и даете им возможность рисовать себя.
Хотя это довольно хорошо работает в простой игре с простым рендерингом вперед, это часто приводит к нескольким гигантским игровым объектам, которым нужно хранить свои модели, множественные текстуры и, что хуже всего, метод толстого рисования, который создает тесную связь между игровым объектом, текущая стратегия рендеринга и любые классы рендеринга.
Если бы я изменил стратегию рендеринга с прямой на отложенную, мне пришлось бы обновить множество игровых объектов. И игровые объекты, которые я делаю, не так многоразовы, как могли бы быть. Конечно, наследование и / или композиция могут помочь мне бороться с дублированием кода и немного упростить изменение реализации, но все еще ощущается недостаток.
Возможно, лучшим способом было бы полностью удалить метод Draw из класса GameObject и создать класс Renderer. GameObject по-прежнему должен содержать некоторые данные о его визуальных элементах, например, какую модель он должен представлять и какие текстуры должны быть нарисованы на модели, но как это сделать, будет оставлено для визуализации. Однако при рендеринге часто встречается много граничных случаев, поэтому, хотя это устранит тесную связь между GameObject и Renderer, Renderer все равно должен был бы знать все игровые объекты, которые делали бы его жирным, все знали и тесно связаны. Это нарушило бы немало хороших практик. Возможно, Data-Oriented-Design справится с этой задачей. Игровые объекты, безусловно, будут данными, но как будет управлять этим средством визуализации? Я не уверен.
Так что я в растерянности и не могу придумать хорошего решения. Я пытался использовать принципы MVC, и в прошлом у меня были некоторые идеи о том, как использовать это в играх, но в последнее время это не кажется таким применимым, как я думал. Я хотел бы знать, как вы все решаете эту проблему.
В любом случае, давайте повторим, мне интересно, как можно достичь следующих целей дизайна.
- Нет логики рендеринга в игровом объекте
- Слабая связь между игровыми объектами и движком рендеринга
- Не все знающие рендерер
- Предпочтительно переключение во время выполнения между движками рендеринга
Идеальная настройка проекта - это отдельная «игровая логика» и проект логики рендеринга, которые не должны ссылаться друг на друга.
Этот мысленный ход начался, когда я услышал, как Джон Кармак сказал в твиттере, что у него настолько гибкая система, что он может менять движки рендеринга во время выполнения и даже может сказать своей системе использовать оба рендерера (программный рендер и аппаратно-ускоренный рендерер) в то же время, чтобы он мог проверять различия. Системы, которые я запрограммировал до сих пор, даже не настолько гибки