2010-02-03 3 views
16

Должны ли сущности знать, как нарисовать себя? Я использовал этот подход: он прост и работает, но после изучения MVC-шаблонов я чувствую себя неловко об этом. Трудно изменить стиль искусства, когда вся логика дисплея похоронена в модели.Игры: Кто несет ответственность за отображение?

Можно было бы представить класс вида, который принимает уровень как аргумент и рисует его, но это будет означать, что он должен идентифицировать типы сущностей и ввести «switch» -statement, о котором я узнал, также плохо.

Где следует размещать код для рисования, способным к растяжению, легко меняющимся, чистым и сухим?

+1

В инструкции переключателя нет ничего плохого. Что-то не так с оператором switch, который имеет ту же структуру в нескольких местах, что обычно подразумевает, что вы должны использовать виртуальную функцию. – MSN

+0

Оператор switch - это просто переопределение goto. Выводы переключателей неплохие. Они просто приводят к гигантским беспорядкам с течением времени - например, они копируют/вставляют * магниты *. – sylvanaar

+0

+1 - отличный вопрос. – Finglas

ответ

5

Нет ничего изначально неправильного в том, что у вас есть абстрактный метод Draw() в ваших сущностях, который позволяет им решать, как они будут нарисованы, особенно для небольших игр, которые, вероятно, не будут значительно расширены. Я использовал этот метод в тоннах небольших проектов, и он отлично работает.

Улучшение, которое вы можете внести в эту стратегию, заключается в использовании ваших игровых ресурсов в качестве прокси-сервера для реальных операций рисования. Например, объект-противник может отложить все рендеринг через принадлежащий ему ресурсный объект, который представляет сетку; также для текстуры/кожи и эффектов.

Я недавно переключился на использование моих объектов как «немых» контейнеров для интерфейсов, которые определяют их поведение. Объект игрока может содержать IMoveable, IControllable, Irenderable и многие другие интерфейсы, которые просто применяют специализированную операцию к этому объекту в зависимости от содержащихся в нем данных. Сущность не знает об этом, и все выполнение происходит, когда граф сцены пересекается для отбраковки/рендеринга.

3

MVC не обязательно подходит для игр. MVC был разработан для традиционных графических интерфейсов, которые обычно обновляются редко на основе дискретных событий, тогда как игры больше похожи на симуляции, где происходит постоянное обновление, и представление должно отражать это мгновенно.

По-прежнему нет причин, по которым вы не должны пытаться отделить государство от презентации. Сущности не должны знать, как рисовать себя как таковые - это означало бы, что они знают об операциях рендеринга, что необязательно, но должно быть возможно спросить их, как они выглядят в этот момент времени, а затем использовать эту информацию для визуализировать сцену. например. 2D-объект должен иметь возможность возвращать текущий кадр анимации. Или 3D-объект должен иметь возможность вернуть свою 3d-сетку, положение и ориентацию. Здесь нет необходимости в инструкции switch, если у вас есть общие представления, которые вы можете вернуть рендереру. Сущности с дико отличающимися алгоритмами рендеринга, возможно, должны будут возвращать в этот момент довольно разные объекты.

+0

Это напрямую не связано с вопросом, но если вы пойдете с описанным вами подходом, кто должен отвечать за обработку таких ресурсов, как текстуры? Объект, средство визуализации или какой-либо другой объект? –

+0

Текстуры представляют собой деталь реализации презентации, поэтому они не будут находиться в объекте напрямую. Обычно у вас есть те, в каком-то менеджере ресурсов, которые загружаются в том месте, где вы загружаете спрайт или сетку для объекта. Сущность знает, какой спрайт или сетка она использует, и спрайт или сетка знают, какую текстуру (и) они используют. – Kylotan

3

Обычно я решаю этот вопрос с наследованием.

Например, в проекте, над которым я работаю, в настоящий момент я использую Test-Driven Development для написания логики игры с ручным тестированием для рендеринга. Этот пример ниже на C# показывает приблизительную идею.

class GameObjecet { 
    // Logic, nicely unit tested. 
} 

class DrawableGameObject : GameObject { 
    // Drawing logic - manual testing 
} 

Это, как правило, то, что я нашел лучшим решением. Это позволяет тестировать код, не загромождая логику игры с презентационным кодом, таким как рисование и загрузка модели и т. Д.

+0

Как-то это первый раз, когда я это видел, и мне это очень нравится. – Ricket

+0

+1 для обозначения проверяемости. Слишком мало программистов считают, что при выборе дизайна. –

7

Этот вопрос по-прежнему часто возникает при разработке игр, так как различные студии и группы начинаются с новых движков.

Короткий ответ заключается в том, что это зависит от того, насколько сложны ваши игровые объекты. Для простых объектов это не имеет большого значения.

Когда вы попадаете в более сложные объекты, вам необходимо пересмотреть свой подход. В общем, вы захотите противостоять желанию иметь цикл uber, который выполняет итерацию по каждому объекту и вызывает некоторую функцию update/render/whatever. Это совсем не масштабируется, если только каждое обновление, рендеринг или любая другая иерархия не совпадают. Это отлично подходит для такой игры, как Geometry Wars, но не для чего-то более сложного.

Что вы хотите сделать, так это предоставить наиболее общую коллекцию сущностей, которая выберет трафик обхода конкретного использования. Например, если вы хотите визуализировать сцену, у вас должен быть способ извлечения всех визуализируемых объектов из коллекции сущностей, а затем рендеринг всех из них в каком-то произвольном порядке. То же самое относится и к физике, столкновения, AI и т.д.

Некоторые полезные ссылки:

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/ http://research.scee.net/files/presentations/gcapaustralia09/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf

Я настоятельно рекомендую и другое; первый идет в обоснование дизайна для создания игровых объектов из компонентов, то есть компонент рендеринга, физический компонент, компонент ИИ. Второй - характеристики производительности различных подходов к игровым объектам.

Смежные вопросы