Объектно-ориентированные проблемы приложения в разработке игр

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

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

Проблема прибывает, когда я должен сделать другие вещи в дополнение только к изменению положения плееров. Например, скажите, что я должен отправить то событие деформации другим плеерам в онлайн-игре. Это должно кодировать также быть в деформации Игрока () методом? В противном случае тогда я предположил бы объявлять, что в некотором вторичном методе в говорится что класс Сервера как warpPlayer (плеер, положение). Выполнение этого, кажется, уменьшает все, что игрок делает к себе как серия методов get и методов set, или является мной просто неправильно здесь? Это - что-то, что это полностью нормально? Я считал бесчисленные времена, что класс, который представляет все как серию методов get/методов set, указывает на довольно плохую абстракцию (используемый в качестве структуры данных вместо класса).

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

Поскольку ООП является методологией проектирования, наиболее используемой сегодня (я принимаю?), там получен, чтобы быть чем-то, что я пропускаю относительно этих проблем. Я обсудил это со своими коллегами, которые также освещают разработку, и у них также также были эти точно те же самые проблемы с ООП. Возможно, это просто, что фон структурного программирования, который мешает нам понимать полные преимущества ООП как что-то большее чем предоставлять методы, чтобы установить и получить частные данные так, чтобы это было изменено и получено от одного места.

Заранее спасибо, и надо надеяться я не звучу совсем как идиот. Для тех, кто действительно должен знать языки, связанные с этим дизайном, это - Java на стороне сервера и ActionScript 3 на стороне клиента.

9
задан suinswofi 25 December 2009 в 12:26
поделиться

7 ответов

Не волнуйтесь слишком сильно о классе Player как о кучке сеттеров и геттеров. Класс Player является классом модели, и классы модели, как правило, такие. Важно, чтобы классы модели были маленькими и чистыми, так как они будут использоваться по всей программе. Я думаю, что Вы должны использовать предложенный Вами подход warpPlayer(player, position). Он сохраняет класс Player чистым. Если Вы не хотите передавать плеер в функцию, возможно Вы могли бы использовать класс PlayerController, который содержит объект Player и метод warp(Position p). Таким образом, вы можете добавить сообщение о событии в контроллер, и держать его подальше от модели.

Что касается сохранения плеера, я бы сделал это, заставив Player реализовать какой-нибудь интерфейс сериализации. Класс плеера сам отвечает за сериализацию и снятие сериализации, а какой-нибудь другой класс будет отвечать за запись сериализованных данных в/из файла.

1
ответ дан 3 November 2019 в 07:13
поделиться

Советую не бояться того, что игрок будет классом геттеров и сеттеров. Что такое предмет? Это компиляция атрибутов и поведения. На самом деле, чем проще ваши классы, тем больше преимуществ ООП вы получите в процессе разработки.

Я бы разбил ваши задачи/функции на такие классы:

Player:

  • имеет атрибут hitpoints
  • имеет атрибут position
  • can walkTo(position), стреляя "walk" events
  • can healUp(hitpoints)
  • can takeDamage(hitpoints), стреляя "isHurt" event
  • can be check for still living, like isAlive() method

Fighter extends Player (вы должны быть в состоянии отдать игрока в Fighter, когда это необходимо) :

  • имеет силу и другие боевые параметры для вычисления урона
  • может атаковать() стреляя "атакующим" событием

Мир следит за всеми игроками:

  • прислушивается к событиям "ходьбы" (и предотвращает незаконные перемещения)
  • перечисляет события "isHurt" (и проверяет, живы ли они еще)

Бой управляет сражениями между двумя бойцами:

  • конструктор с двумя бойцами в качестве параметров (вы хотите построить бой только между игроками, которые действительно сражаются друг с другом)
  • прислушивается к "атакующим" событиям обоих игроков, вычисляет урон и выполняет метод takeDamage защищающегося игрока

PlayerPersister расширяет абстрактный метод AbstractPersister:

  • сохраняет состояние игрока в базе данных
  • восстанавливает состояние игрока из базы данных

Конечно, сбой в игре будет намного сложнее, но я надеюсь, что это поможет вам начать думать о проблемах "больше ООП" :)

.
4
ответ дан 3 November 2019 в 07:13
поделиться

Я бы, наверное, подумал о том, чтобы иметь Игровой объект, который отслеживает игровой объект. Так что вы можете сделать что-нибудь вроде game.WarpPlayerTo(WarpLocations.Forest); Если есть несколько игроков, может быть, пропустите объект игрока или направляющую с ним. Я чувствую, что вы все еще можете сохранить его OO, и игровой объект решит большинство ваших проблем, я думаю.

0
ответ дан 3 November 2019 в 07:13
поделиться

Описываемые вами проблемы относятся не только к проектированию игр, но и к архитектуре программного обеспечения в целом. Общим подходом является наличие механизмов Впрыска зависимости (DI) и Инверсии управления (IoC). Короче говоря, вы пытаетесь достичь возможности доступа к локальному Service вроде как из ваших объектов, чтобы, например, распространить какое-либо событие (например, искривление), журнал и т.д.

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

.
0
ответ дан 3 November 2019 в 07:13
поделиться

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

В этом случае, я бы посоветовал, что вы разрабатываете данные, которые должны быть синхронизированы между всеми клиентами, и хранить их в одном классе (например, GameState). Этот объект будет обрабатывать всю синхронизацию между различными ПК, а также позволит вашему локальному коду запрашивать изменения в данных. Затем он "привезет" игровые объекты (Player, EnemyTank и т.д.) из своего состояния. [редактировать: причина в том, что сохранение этого состояния как можно меньше и эффективная передача его между клиентами будет ключевой частью вашего дизайна. Сохраняя все это в одном месте, это значительно облегчает задачу, и поощряет вас ставить только самое необходимое в этот класс, чтобы ваши комиксы не раздувались от ненужных данных]

Если вы не делаете мультиплеер, и вы обнаружили, что изменение позиции игрока требует обновления нескольких объектов (например, в случае, если у вас есть несколько объектов, которые вы хотите обновить)

. g. ты хочешь, чтобы камера знала, что игрок переместился так, чтобы она могла следить за ним), тогда хорошим подходом будет сделать так, чтобы игрок отвечал за свою позицию, но поднимать события/сообщения, на которые другие объекты могут подписаться/слушать, чтобы знать, когда позиция игрока меняется. Таким образом, вы перемещаете игрока, и камера получает обратный вызов, говоря ему, что позиция игрока была обновлена.

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

.
0
ответ дан 3 November 2019 в 07:13
поделиться

Иногда фокус ООП состоит в том, чтобы понять, что такое объект, и что такое функциональность объекта. Я думаю, что часто нам довольно легко концептуально закрепить такие объекты, как Player, Monster, Item, и т.д. в качестве "объектов" в системе, а затем нам нужно создать объекты, такие как Environment, Transporter, и т.д., чтобы связать эти объекты вместе, и это может выйти из-под контроля в зависимости от того, как концепции работают вместе, и что нам нужно сделать.

У действительно хороших инженеров, с которыми я работал в прошлом, был способ воспринимать системы, как коллекции объектов. Иногда в одной системе это были бизнес-объекты (например, элемент, счет-фактура и т.д.), а иногда это были объекты, инкапсулирующие логику обработки (DyeInjectionProcessor, PersistanceManager), которые пересекали несколько операций и "объектов" в системе. В обоих случаях метафоры работали именно для этой системы и облегчали реализацию, описание и сопровождение всего процесса в целом.

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

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

*.
0
ответ дан 3 November 2019 в 07:13
поделиться

Я бы хотел расширить последний абзац GrayWizardx, чтобы сказать, что не все объекты должны иметь одинаковый уровень сложности. Вполне может подойти ваш дизайн, чтобы иметь объекты, которые представляют собой простые коллекции get/set свойств. С другой стороны, важно помнить, что объекты могут представлять задачи или коллекции задач, а не реальные объекты. Например, объект игрока может не отвечать за перемещение игрока, а представлять его позицию и текущее состояние. Объект PlayerMovement может содержать логику изменения позиции игрока на экране или в игровом мире.

Прежде чем я начну просто повторять то, что уже было сказано, я укажу на SOLID принципы ООП-дизайна (Aviad P. уже упоминал два из них). Они могут предоставить некоторые руководящие принципы высокого уровня для создания хорошей объектной модели для игры.

.
0
ответ дан 3 November 2019 в 07:13
поделиться