Два класса, зависящие друг от друга - PullRequest
2 голосов
/ 18 октября 2010

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

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

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

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

Но мне не нравится ни один из этих:

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

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

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

Ответы [ 5 ]

2 голосов
/ 18 октября 2010

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

1 голос
/ 18 октября 2010

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

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

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

1 голос
/ 18 октября 2010

Две альтернативные опции:

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

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

1 голос
/ 18 октября 2010

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

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

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

0 голосов
/ 18 октября 2010

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

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

Это не красиво, и камера везде раздается, но она работала хорошо.

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...