Разделяю ли я и как разделяю проблемы входных и игровых объектов?

20

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

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

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

Какие стратегии вы используете для этого?

Роберт Масса
источник

Ответы:

7

Я рекомендую отделять входные события от игровых объектов, чтобы вы могли быстро изменять / обновлять методологии ввода без необходимости редактировать и отлаживать 10 классов объектов. Примеры перехода от управления только с клавиатуры на мышь + клавиатура или просто переназначение клавиш.

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

Используйте контроллер ввода, чтобы отслеживать состояние ввода:

Up press event   -> dir = up
Down press event -> dir = down

Всякий раз, когда изменяется состояние ввода, оцените, готовы ли игровые объекты к изменению:

set dir  ->  if gamestate != paused && battlemode == false
             ->  character.changeDir(dir);

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

changeDir (dir)
setSpeed (walk/run)
эдвардианский
источник
7

Я рекомендую подход MVC. В MVC игровые объекты должны беспокоиться только о моделировании игровой системы и предоставляют интерфейс высокого уровня, такой как move_left. Затем есть объект контроллера, который беспокоится о отображении ввода в вызовы модели. Он не только позволяет легко менять элементы управления, но и дает хороший интерфейс для ИИ, это всего лишь еще один контроллер.

Во втором варианте я бы разделил контроллер ввода на две части: одну, которая обрабатывает фактическое касание устройства, клавиатуру, ускорение, все, что вы можете на него бросить, чтобы он отображал их в общий набор входов. Затем есть вторая часть, которая отображает общие входные данные для конкретных входных данных игры. Скажем, стрелка вверх на клавиатуре отображается на input1, затем касание верхней части сенсорного экрана также отображается на input1, и теперь вы пишете вторую часть, которая отображает ввод 1 для перехода. Теперь вы можете сопоставить любое устройство ввода-вывода, а также сохраненные входы воспроизведения или AI с этой общей системой ввода и иметь небольшую специфичную для игры часть, которая загружает значение input1, одно из них, для модели.

stonemetal
источник
5
На этом сайте много дискуссий о том, почему MVC вообще не подходит для игр; то, что описывает Stonemetal, - это даже не MVC, а просто абстракция; и «Использовать MVC» не является ответом, поскольку MVC - это описание целого класса архитектур, а не конкретный способ разделения проблем (и не единственный способ сделать это).
2
MVC должен дать ему A) статью в Википедии, чтобы прочитать B) несколько вариантов того, как подходить к решению, которое, как было показано, работает C) Я упомянул способ, которым я бы настроил его, когда модель предоставляет интерфейс высокого уровня, который Контроллер отображает вход низкого уровня (реальный или синтетический) на действие высокого уровня и напрямую манипулирует моделью, а не какой-либо системой обработки событий.
каменный металл
1

Я бы предложил, чтобы ваша игра ( Модель ) определила список возможных входных событий (реализованных в виде перечислений или объектов с общим базовым интерфейсом). Вещи , такие как MovingRightStarted, MovingRightStopped, FiredWeapon1, Escapeи т.д. ...

Игра определяет структуру данных (например, а queue), которую ваш входной код ( контроллер ) может заполнять входными событиями.

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

Таким образом, вы можете подключить различные типы контроллеров для питания модели:

  • Только клавиатура
  • Клавиатура + Мышь
  • Джойстик
  • Сенсорный экран
  • Искусственный интеллект

Вы просто хотите, чтобы они передавали входные события в модель.

Splo
источник
Я думаю, я понимаю, что вы имеете в виду, за исключением того, что вы выбираете queueтип данных для хранения этого. Не могли бы вы объяснить, почему?
Роберт Масса
Между двумя опросами входных событий из модели контроллер, возможно, выдвинул несколько событий действия, и важно сохранить порядок пользовательского ввода. Вот почему я выбрал структуру данных FIFO. На самом деле вам также может понадобиться указать, в какое именно время произошел ввод.
Спло