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

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

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

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

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

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

Ответ 1

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

Например:

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);
   } 
}

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

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

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

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

Ответ 7

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

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

Ответ 8

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

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