Сериализация объектов для функции отмены / возврата Java - PullRequest
3 голосов
/ 12 марта 2010

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

Ответы [ 3 ]

3 голосов
/ 12 марта 2010

Программирование игр не имеет ничего общего ни с программированием «корпоративных приложений», ни с «программированием веб-приложений».

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

Великолепные игры, такие как, например, Warcraft III от Blizzard или Age of Empires от Microsoft, когда-либо хранят только пользовательские данные, необходимые для воспроизведения любого игрового состояния .

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

Как это связано с отменой / повтором? Trivial ...

Представьте, что с момента запуска игры у вас было 200 пользовательских входов, и вы хотите отменить последний шаг: вы запускаете игру с нуля и набираете 199 первых входных данных. Вот и все. Совершенная отмена.

Конечно, вам нужно только воспроизвести логику при воспроизведении этих 199 шагов, без необходимости обновления вашего представления. Для большинства игр логика - это крошечная часть общего времени, затраченного на просмотр (большая часть времени тратится на просмотр). Поэтому воспроизведение этих входов происходит очень быстро.

Был там, сделал это:)

Теперь, если вы хотите другой способ сделать неограниченную отмену / повтор, тогда нужно кое-что сказать о «OO поверх неизменяемых объектов»: я написал редакторы игровых инструментов (например, редактор карт) с неограниченным отменить / повторить тоже. Хитрость в том, чтобы только когда-либо использовать неизменяемые объекты. Тогда сохранить прежние состояния легко: просто объект на вершине вашей иерархии ('gamemap239').

Поскольку вы когда-либо используете только неизменяемые объекты, «новая» игровая карта разделяет 99,9% своих объектов с предыдущей игровой картой, и, следовательно, использование памяти невероятно низкое, что позволяет сохранять огромное количество состояний.

Я успешно применил это «OO поверх неизменяемых объектов для эффективного отмены / повтора» в коммерческих программах, которые не являются играми, и это действительно удивительная техника.

Теперь все зависит от игры, которую вы делаете: конечно, для игры тральщика вы можете использовать Swing и обычные методы программирования Java. Но для более продвинутых игр обычные Java-коллекции и API-интерфейсы, а также обычные приемы программирования entreprise / webapp / fatclient просто не позволяют этого сделать

2 голосов
/ 12 марта 2010

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

Редактирование, которое можно отменить, состоит из 3 важных частей: конструктор, метод отмены и метод повторения. Хитрость заключается в том, чтобы сделать каждое «редактирование» ОЧЕНЬ простым. В зависимости от сложности вашей игры, между «ходами» могут быть сотни правок.

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

Каждый тип редактирования - это другой тип объекта. Допустим, вы перемещаете юнит из (35,150) в (35, 151). Ваш ход может выглядеть так:

undoManager.addEdit( new MoveOne(map, new Point(35,150), new Point(35,151)) );

и отмена этого редактирования будет просто:

undoManager.undo();

, который автоматически отменяет все до последнего «значительного» редактирования (последнего, сделанного игроком-человеком)

Вот как будет выглядеть класс «move»:

MoveOne extends AbstractUndoableEdit {
    private final Point start;
    private final Point finish;
    private final Map map;

    public MoveOne(Map pMap, Point pStart, Point pFinish) {
        start=pStart;
        finish=pFinish;
        map=pMap;
        redo();
    }

    public redo() {
        MapObject piece=map.getObjectAt(start);
        map.moveObject(piece, finish);
    }

    public undo() {
        MapObject piece=map.getObjectAt(finish);
        map.moveObject(piece, start);
    }
}

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

Мне нравится этот шаблон, и я обращаюсь к @Kaleb за указанием, что java теперь поддерживает его в JDK!

2 голосов
/ 12 марта 2010

Java предоставляет javax.swing.undo.UndoManager, который по сути является стеком UndoableEdit (т. Е. Команд). Если вы сохраняете состояние «до» и «после» в UndoableEdit, то всякий раз, когда вы запускаете отмену или повтор, это просто вопрос восстановления этого состояния при отмене или повторении.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...