2010-10-18 8 views
2

У меня есть класс камеры, который управляет поведением камеры. Среди его полей есть ссылка на класс Cube для цели (куб - это только один из объектов, но я не буду упоминать других, чтобы они были простыми). Чтобы вычислить матрицу View, мне нужна позиция камеры и позиция цели, поэтому я могу объяснить моей программе, что: «камера размещена здесь, и отсюда она смотрит на этот куб». Если куб будет перемещаться, то и точка зрения камеры автоматически изменится.Два класса, зависящие друг от друга

До сих пор все хорошо: есть класс камеры, который зависит от класса Cube, и есть класс Cube, который ни на что не зависит (в этом примере).

Я добираюсь до проблемы, когда мне нужно нарисовать куб, или что-нибудь else - для того, чтобы нарисовать что-то, среди необходимых значений - матрица вида Camera; это тот, который я только что вычислил в первом абзаце. По сути, это означает, что когда я добираюсь до места, чтобы нарисовать вещи на экране, класс Cube также зависит от класса Camera, и теперь они зависят друг от друга. Это означало бы, что я либо:

  1. Необходимо сделать поле «Просмотр матрицы» класса «Камера» статическим, поэтому я могу получить к нему доступ непосредственно из класса Cube.
  2. необходимо выполнить метод (например SetView) в классе Cube, который затем я могу вызвать из класса Camera (так как у меня уже есть ссылка).
  3. Необходимо сохранить матрицу вида во внешнем пространстве.
  4. необходимо сделать двунаправленную зависимость.

Но мне не нравится любой из них:

  1. больше камер, которые обрабатывать несколько представлений (в настоящее время есть 3 из них на экране), и может быть больше (или меньше).
  2. это делает код немного (иногда, может быть, очень) нечитаемым - например, когда я рисую куб, неясно, откуда взялась матрица View, вы просто используете его и не смотрите назад ,
  3. Я бы получил доступ к внешнему виду из класса камеры, или внешняя область доступа к камере, и мне это не понравится, потому что внешняя область используется только для обработки механики выполнения.
  4. Мне нравится сохранять мои ссылочные поля «readonly», поскольку в настоящее время это происходит повсюду в этой системе - ссылки задаются в конструкторе и используются только для получения данных из ссылочных классов.

И, если я не прояснил это, позвольте мне просто повторить, что есть несколько объектов камеры и несколько объектов Cube; в то время как любая Камера может или не может зависеть от любого Куба, но обычно есть, по крайней мере, одна Камера, зависящая от Куба.

Любые предложения будут оценены :)

ответ

2

Если ваш кубик должен знать, как сделать себя относительно камеры (и, следовательно, должен знать о Камере), то, вероятно, для камеры не имеет смысла знать, как выровнять себя с кубом. Поведение выравнивания, которое в настоящее время находится в Camera, вероятно, принадлежит к классу более высокого уровня, например CameraDirector, который знает обо всех Cubes и Cameras. Это улучшает сцепление классов, поскольку оно отрывает некоторые из обязанностей камеры в другом, сильно фокусированном классе CameraDirector. Это позволяет фокусировать камеру на основной работе и упрощает ее понимание и поддержку.

+0

Спасибо, что заметили ... Мне нужно сделать несколько тестов, прежде чем принимать этот ответ, но теперь вы даете мне представление о том, что мне следует делать - сделайте что-то вроде метода Camera.Attach (IAttachable attachTo) 'в Класс камеры, где я могу заказать камеру, чтобы следить за этим объектом ... и в этом случае я инвертирую текущую зависимость. – avance70

+0

Да, я перекодировал эту часть, и мне кажется, что это лучшее решение. – avance70

1

Предполагая, что ваш DrawWorld() рутина уже знает о Cube с и Camera с, я бы передать матрицу вида на Draw() метода Cube «s:

foreach (Cube cube in cubes) { 
    cube.Draw(..., mainCamera.ViewMatrix, ...); 
} 

Это путь Cube только «зависит» от Matrix и не на Camera. Опять же, возможно, это нарушает правило 3 выше.Тем не менее, я не могу сделать ничего лучше, не видя некоторых из вашего кода.

+0

Это то, что я использовал с самого начала - это было, когда у меня была только одна камера. Я столкнулся с этой проблемой, когда представил несколько камер (подумайте об этом как зеркало заднего вида в гоночных играх). Поэтому было сложно справиться с этим так: – avance70

1

два альтернативных варианта:

  1. Создание базовых классов для камеры и кубы, которые не связывают друг с другом, но по-прежнему содержат большую часть логики вы хотите использовать. Затем вы можете добавить ссылку BaseCamera на Cube, которой вы бы назначили объект Camera, а не объект BaseCamera. (И камера с полем BaseCube.) Это сила полиморфизма.
  2. Определите интерфейс ICamera и ICube. Затем класс Camera использовал поле ICube для связи с кубом и наоборот.

Оба решения потребуют от вас заботиться при создании и освобождении новых объектов камеры и куба. Мое личное предпочтение будет заключаться в использовании интерфейсов. Имейте в виду, что интерфейсы ICube и ICamera должны не ссылки друг на друга. Связанные с ними классы свяжутся с другим интерфейсом, но не с интерфейсами.

+0

Спасибо, немного сложно работать над иерархией объектов (давайте просто скажем, что это не в * my * domain, чтобы разобраться в этом), но вы правы, если думаете, что есть не так много иерархии объектов в решении. Это то, что мне пришлось бы обсудить с другими вовлеченными людьми. Thoigh. Думаю, мы дошли до точки, где можно было бы установить лучшую иерархию, так как сейчас у нас есть только несколько интерфейсов. – avance70

0

При выполнении XNA у меня была силиловая проблема.

Я разрешил это, добавив интерфейс к камере в свой интерфейс метода Draw.

Его не очень красиво, и камера проходит везде, но она хорошо работает.

Реальная вещь - это то, что ваши петли обновления и рисования являются отдельными.

При рисовании у вас есть список объектов для рисования, и ваша процедура рисования имеет некоторый класс камеры, переданный ему.

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

Суть в том, что список камер поддерживается вместе со списком доступных объектов, несмотря на то, что все эти объекты также относятся к логическому шаблону, описывающему состояние игры.

Читайте об инверсии элемента управления. Это все, что я описываю на самом деле.

1

Я сделал каждый класс объектов ответственным за его собственный рендеринг.

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

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

+0

Я также сделал каждый класс ответственным за его собственный рендеринг :) спасибо, что напомнил мне о проблемах с расстоянием, я думаю, что я не передал эту часть кода в новое решение. – avance70

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