Лучший способ реализовать воспроизведение игры?

Я создаю игру на основе сетки на Java, и я хочу реализовать запись и воспроизведение игры. Не знаю, как это сделать, хотя рассмотрел 2 идеи:

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

  2. Я также мог записывать каждое нажатие клавиши и щелчок мышью в файл сохранения. Это дало бы мне файл меньшего размера и могло бы воспроизводить с меньшими задержками. Однако малейшая ошибка в начале игры (например, съемка на 1 миллисекунду позже) приведет к совершенно иному игровому состоянию через несколько минут после начала игры.

Как тогда лучше всего реализовать воспроизведение игры?

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


person Lucky    schedule 28.04.2009    source источник


Ответы (8)


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

Например:

public interface Command{
    void execute();
}
public class MoveRightCommand implements Command {
   private Grid theGrid;
   private Player thePlayer;

   public MoveRightCommand(Player player, Grid grid){
        this.theGrid = grid;
        this.thePlayer = player;
       }

   public void execute(){
     player.modifyPosition(0, 1, 0, 0);
   } 
}

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

person Aleris    schedule 28.04.2009
comment
Это элегантный способ справиться с этим. Если фактический игровой процесс и запись основаны на одном и том же механизме синхронизации / кадра, вам следует избегать ошибок из-за проблем с синхронизацией. Если у вас есть рандомизация в ваших событиях, вам может потребоваться записать начальное начальное значение для вашего генератора случайных чисел. Вот как функции «Случайная карта» в играх RTS позволяют вам воссоздать случайную карту, которая вам понравилась. - person Steven Richards; 29.04.2009
comment
Этот шаблон также может дать вам возможность отмены / возврата. - person Bill the Lizard; 29.04.2009

Шон Харгривз недавно опубликовал в своем блоге сообщение о том, как они реализовали воспроизведение в MotoGP. Рассмотрены несколько различных подходов, их плюсы и минусы.

http://blogs.msdn.com/shawnhar/archive/2009/03/20/motogp-replays.aspx

person Michael    schedule 28.04.2009

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

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

Рассмотрим, например, такую ​​игру, как Halo 3 для XBOX 360 - каждый клиент записывает свой взгляд на игру, включая исправления на сервере.

person Uri    schedule 28.04.2009

Почему бы не записывать несколько раз в секунду, а затем сжимать результат, или, возможно, сделать это:

recordInitialState();
...
runs 30 times a second:
recordChangeInState(previousState, currentState);
...

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

person CookieOfFortune    schedule 28.04.2009

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

person Daniel    schedule 28.04.2009

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

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

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

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

person James Black    schedule 28.04.2009

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

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

person Kylotan    schedule 28.04.2009

Однажды я сделал это, позаимствовав идею сжатия видео: ключевые и промежуточные кадры. По сути, каждые несколько секунд вы сохраняете полное состояние мира. Затем, один раз за обновление игры, вы сохраняете все изменения состояния мира, произошедшие с момента последнего обновления игры. Детали (как часто вы сохраняете ключевые кадры? Что именно считается «изменением состояния мира»?) Будут зависеть от того, какую информацию об игре вам нужно сохранить.

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

person David Seiler    schedule 11.06.2009