Как вы можете упорядочить код для игры в соответствии с шаблоном MVC?

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

У меня есть класс Java, поэтому я отбросил свои исследования и разработки на С++ и перешел в Java и JOGL (Java OpenGL). Это замечательно! Но это не относится к делу.

Я хочу сделать небольшую ролевую игру, но этот вопрос действительно относится к любой игре. Как вы упорядочиваете игровые объекты таким образом, который структурирован, как шаблон Model-View-Controller? Это выглядит потрясающе, очень широко используется и имеет большой смысл, но мне трудно понять, как его реализовать.

Например, мне нужно отслеживать объект GL для рисования на экране. Я должен иметь классы, которые реализуют MouseListener, MouseMotionListener, MouseWheelListener и KeyListener (или один класс, менеджер ввода-вывода "все-в-одном" ). И я должен поместить свои игровые данные где-нибудь, где все эти разные классы могут получить доступ и изменить его; если кто-то нажимает кнопку на клавиатуре, класс управления вводами должен каким-то образом выполнить действие, к которому привязан ключ; когда кадр должен быть нарисован, графическому классу необходимо найти способ перебрать все разные "вещи" и нарисовать их все.

И моя самая большая проблема, GUI; где он привязан ко всему этому? Это что-то вроде ввода, но не совсем, и ему нужно как установить, так и получить кусочки данных из фактического игрового моделирования... И усложнять его даже БОЛЕЕ, если я решит попробовать и добавить сети, которые (подобно графическому интерфейсу ) также должен иметь доступ к большому количеству данных для изменения и чтения...

О, я просто смущен. Я не знаю, как сделать все это совместной работой объектно-ориентированным способом... Это достаточно легко писать вещи, которые явно соответствуют шаблонам, но когда у вас много вещей, которые все связаны с одним игровым циклом, изменяя друг друга и данные игры и т.д., я даже не знаю. Возможно, я просто делаю это крупнее, чем на самом деле.

Кто-нибудь еще так чувствовал? Пожалуйста, предложите некоторую ясность в моей ситуации, чтобы я мог тратить меньше времени на беспокойство и не знать, с чего начать!

-Ricket

Изменить: Найдена хорошая диаграмма, которая может помочь мне понять все это... Источник: (остерегайтесь, файл PS!) http://www.tucs.fi/publications/attachment.php?fname=TR553.ps.gz

http://img10.imageshack.us/img10/6278/mvcdiagramgamesbl5.png

Edit2: Мне также нравится, что этот парень объясняет, как он планировал свою игру MVC: http://interactivesection.wordpress.com/2007/11/19/dum-de-dum-drum-my-first-mvc-game-development/

Edit3: Еще одна замечательная статья! http://dewitters.koonsolo.com/gamemvc.html

Ответ 1

Это может помочь вам придумать модель как своего рода игровой API. Что бы ваша игра была сведена до того, что не было никакого интерфейса для игры, посвященной с самого начала? Вы упомянули, что вы имеете в виду RPG, поэтому в этом случае вы можете представить себе персонажа игрока, его/ее инвентарь, заклинания, способности, NPC и даже такие вещи, как карты и боевые правила, все из которых являются частью модели, Это похоже на правила и части Монополии без специфики того, как финальная игра отображает это или как пользователь будет взаимодействовать с ним. Это похоже на Quake как абстрактный набор трехмерных объектов, перемещающихся по уровню с такими вычислениями, как пересечение и столкновение, но без рендеринга, теней или звуковых эффектов.

Поместив всех в модель, сама игра теперь является агностиком. Его можно подключить к текстовому интерфейсу ASCII, например, к игре Rogue, или к пользовательскому интерфейсу командной строки, близкому к Zork, или к веб-интерфейсу или 3D-интерфейсу. Некоторые из этих пользовательских интерфейсов могут быть ужасными в зависимости от игровой механики, но все они будут возможны.

Уровень просмотра - это зависимый от пользовательского интерфейса слой. Он отражает конкретный выбор пользовательского интерфейса, с которым вы столкнулись, и будет очень много посвящен этой технологии. Это может быть связано с чтением состояния модели и ее рисованием в 3D, ASCII или изображениях и HTML для веб-страницы. Он также отвечает за отображение любых механизмов управления, которые игрок должен использовать для взаимодействия с игрой.

Уровень контроллера - это клей между ними. Он никогда не должен иметь в себе никакой логической логики и не должен отвечать за управление слоем "Вид" . Вместо этого он должен перевести действия, предпринятые в слое "Вид" (нажатие на кнопки, щелчок по областям экрана, действия джойстика и т.д.) На действия, предпринимаемые на модели. Например, сброс предмета, атака NPC, что угодно. Он также отвечает за сбор данных и выполнение любого преобразования или обработки, чтобы облегчить отображение слоя "Вид" .

Теперь, как я описал это выше, как будто существует очень четкая последовательность событий, играющая в игру, которая, вероятно, действительно подходит только для веб-игры. Это потому, что я потратил свое время на последнее время. В игре, которая не управляется запросом пользователя и ответом сервера, как веб (например, игра, работающая на пользовательской машине), вы, вероятно, захотите убедиться, что на уровне модели реализован шаблон Observer. Например, если в модели происходят действия, потому что время проходит, вам может не потребоваться, чтобы слой "Просмотр" постоянно опросил модель для обновлений. Вместо этого, используя шаблон Observer, Модель могла бы уведомить любых наблюдателей об изменениях объектов Модели, как они происходят. Это, в свою очередь, может быть использовано для немедленного обновления представления, чтобы отразить это изменение.

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

Ответ 2

Вы поедете туда. в основном, задайте себе вопрос "какой код изменится, если мне придется изменить часть программы?"

Если это изменит способ, которым он выглядит, не меняя базовые данные, тогда он отображается в представлении. Если это данные, которые можно просмотреть по-разному, это модель. И если это так, как вы играете, то это контроль.

Итак, если вы нарисуете "топор" с двумя лезвиями или одним, то увидите. Если это количество ударов, наносимых вам урона топором, оно моделируется. И если это, если вы качаете топор, набрав "s" или щелкнув правой кнопкой мыши, он будет управлять.

Ответ 3

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

Я предлагаю прочитать "Шаблоны проектирования" группой из четырех человек. Есть много полезных шаблонов, кроме MVC. Иногда вообще не имеет смысла использовать MVC. Специально для игр я не уверен, что MVC - такая хорошая идея. Причина в том, что вы не хотите отображать игровой объект разными способами (представлениями), но вы хотите повторно использовать код чертежа для разных типов игровых объектов.

Для моего собственного игрового движка 2D я использовал шаблон стратегия довольно активно. Объекты игры, такие как игрок и монстры, я назвал Sprite. Я разрешаю рисованию спрайта с помощью шаблона стратегии. То есть, когда я назвал sprite.draw(), я бы сделал что-то вроде этого:

class Sprite {
  void draw() {
    this.view.draw(this.currentPosition, this.currentOrientation);
  }

  Point  currentPosition;    // Current position of this sprite
  double currentOrientation; // Facing angle of sprite
};

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

В таком поведении я бы также использовал шаблон стратегии, который будет объектом, который содержит код, описывающий поведение. Таким образом, я могу применить одно и то же поведение к нескольким монстрам в другом месте. Поэтому каждый кадр я бы назвал функцией update(), чтобы обновить ориентацию позиции и что делает монстр.

class Sprite {
  void setUpdateAction(Action action) {
    this.updateAction = action;
  }

  void update(double start_time, double delta_time)
  {
    this.prevPosition = position();  
    advance(delta_time); // Advance to next position based on current speed and orientation

    this.updateAction.execute(this, start_time, delta_time);
  }

  Action updateAction;
};

Есть множество вариаций этого. В моей текущей реализации я даже выделил currentPosition, скорость, ориентация и advance() в отдельный объект называется MotionState. Таким образом, я могу построить деревья поиска возможных позиций и ориентации при выполнении алгоритмов поиска пути. Тогда я не хочу нести со мной информацию о том, как вести каждое обновление или как спрайт должен быть нарисован.

Ответ 4

Концепция централизации логики взаимодействия с MVC является хорошей моделью для разработки игр.

Я немного поработал с разработкой Flash-игр. Здесь - статья о пулах объектов во Flash. Концепция кросс-платформенная и может дать вам некоторые идеи.

Вы правы, чтобы беспокоиться о том, что происходит в одно время. В зависимости от вашего игрового дизайна ваш игровой цикл может иметь много общего. Здесь вы узнаете все грязные оптимизационные трюки, часто трудный путь:)

Существует множество способов организовать ваш код. Один вариант - написать класс GameManager в качестве Singleton. Все игровые объекты привязываются к нему для управления и взаимодействия с пользователем. GameManager обрабатывает все сообщения пользователя и отправляет сообщения в пул объектов. Вы можете использовать интерфейсы для определения общих шаблонов связи между игровыми объектами и GameManager.

Что касается оптимизации производительности, потоки очень мощные. Асинхронная операция может гарантировать, что вы не тратите драгоценные циклы.

Ответ 5

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

Ответ 6

Мой образ мышления MVC - это как MDUC
Модель
Дисплей
Пользовательский контроллер ввода

Модель содержит объекты модели домена
На дисплее отображается текущее состояние и поведение объектов модели домена на экране.
Контроллер ввода-вывода обрабатывает все пользовательские входы.

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

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