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

10

Мне было интересно, как реализовать путешествие во времени в игре. Ничего сверхсложного, только обращение времени, как в Braid, где пользователь может перемотать время назад / вперед на 30 секунд или что-то еще.

Я много искал в Интернете, но мои результаты обычно ссылались на использование времени, например «сейчас 3 часа» или на таймер и тому подобное.

Единственное, о чем я мог подумать, - это использовать 2 массива, один для позиции x игрока, а другой для позиции y игрока, а затем перебирать эти массивы и помещать персонажа в эту позицию по мере их перемотки назад / ускоренной перемотки вперед. Может ли это работать? Если это сработает, насколько большим должен быть массив и как часто я должен хранить x и y плеера? Если это не сработает, что еще я могу попробовать?

Заранее спасибо!

Alex
источник
11
Разве вы не читаете новости ( ust.hk/eng/news/press_20110719-893.html )? Они только что показали, что путешествие во времени невозможно. Поэтому невозможно кодировать.
Вам нужно продумать возможную семантику для путешествий во времени, только после этого вы можете начать думать о реализации.
Пауло Эберманн
2
Изучи себе векторную математику . Если вы предлагаете два отдельных массива, это говорит о том, что вы никогда не работали с ними. Я считаю их жизненно важными для программиста игр, потому что они могут многое упростить.
двойник
5
import universal.back2future.FluxCapacitor;
Джоккинг

Ответы:

6

Идея массива очень похожа на то, как она была реализована в Braid. Когда единственными вещами, действующими на персонажа, являются гравитация, ввод с клавиатуры / джойстика и другие символы, вам достаточно всего лишь сохранять положение и скорость на каждом шаге, чтобы знать все важные сведения об этом персонаже. Если вы сохраняете 10 снимков в секунду на каждого персонажа, то за одну минуту истории одного персонажа это все равно менее 50 КБ - это легко управляемо на большинстве систем, и вы также можете найти способы, более эффективные, чем это.

Kylotan
источник
Это правильный путь. Например, хранить активные команды: нажатия клавиш с отметками времени. Вы можете экстраполировать большинство других видов поведения, если система является детерминированной. Трекер с частотой 10 кадров в секунду подходит для системы перемотки, еще меньше может быть приемлемо, если фактические команды сохраняются, в сущности, состояние или изменения состояний объектов.
Кармингтон
4

Читайте о Командном Образце . Он предусматривает отмену действий (и последующее их повторное выполнение). Это будет обрабатывать не только положение корабля, но и все действия, предпринимаемые игроком.

Но я думаю, что твоя идея о массиве тоже правильная.


источник
Возможно, это не очень хорошая идея - помимо того , что она требует больше памяти (каждый раз, когда вы добавляете скорость сущности к ее положению, вам нужно сохранить это как «действие») , она в значительной степени требует математики с фиксированной запятой, так как если вы используете плавающую точку -точка для ваших позиций / скорости, (x+v)-vможет быть не равна x.
BlueRaja - Дэнни Пфлюгофт
1
@BlueRaja - Не вижу, где этот подход будет интенсивно использовать память. При 100 FPS и сохранении последних 10 секунд вам нужно хранить 1000 n-tupels команд, где n не более 5 или около того. Или, что еще лучше, вы сохраняете только абсолютную позицию в каждом из этих кадров, а для перемотки вы просто анимируете персонажа назад по этому пути. Это также устранит любые возможные проблемы с плавающей запятой и вернет вас точно туда, откуда вы начали.
Хакворт,
3

Вместо того, чтобы иметь два отдельных массива, у вас, вероятно, должен быть один класс, который описывает позицию игрока (возможно, в Java уже есть класс Point ... я в последнее время работаю в C #) и использовать один единственный массив для хранения прошлых позиций.

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

Если вы хотите хранить прошлые данные за 30 секунд, вам нужно знать частоту кадров, если вы хотите предварительно выделить пространство и использовать массив фиксированного размера. Если вы рендерите игру со скоростью 10 кадров в секунду, время 30 секунд, это 300 элементов.

Эрик Дж.
источник
2

У GDCVault есть лекция Джона Блоу (создателя Braid ) на их сайте под названием «Реализация перемотки в Braid» за $ 3,95. Готов поспорить, что там есть информация, которую вы хотите;)

РЕДАКТИРОВАТЬ: Вероятно, не будет в Java, но идеи должны держаться.

NoobsArePeople2
источник
Вы знаете, продают ли они также стенограмму или только аудио?
о0 '.
Я не смог ничего найти через быстрый поиск по сайту. Может быть, вы могли бы использовать программное обеспечение транскрипции ?
NoobsArePeople2
1

Как сказал Эрик Дж , сохранение прошлых позиций игрока в виде набора точечных объектов в кольцевом буфере звучит разумно.

Тем не менее, я бы предложил использовать очередь для реализации буфера. Обновление гораздо дешевле, чем массив, и вам не нужно заранее знать частоту кадров:

update():
   time_queue.push(player.positions)
   if current_time() - start_time > n:
       queue.pop()

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

update():
    time_queue.push({
        'pos': player.positions,
        'time': current_time()
    })
    first_entry = queue.peek()
    while current_time() - first_entry['time'] > n:
       queue.pop()
       first_entry = queue.peek()

Надеюсь это поможет!

HumanCatfood
источник
1

Есть шаблон дизайна под названием Memento , я думаю, что это отправная точка для такой игры, как Braid

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

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

http://en.wikipedia.org/wiki/Memento_pattern

Дополнительная информация здесь: http://dofactory.com/Patterns/PatternMemento.aspx

Марсело Ассис
источник
2
Я не понимаю, как это должно помочь. Похоже, это «мгновенный откат», в то время как ОП попросил что-то плавное, как у Брейда. Может я что то не так понял?
о0 '.
Этот шаблон не подразумевает отдельного отката, например, вы можете создать «временную шкалу» действий. Вот сообщение в блоге Brazillian об использовании этого шаблона: abrindoojogo.com.br/padroes-de-projeto-memento Вот пример, сделанный во Flash: abrindoojogo.com.br/files/fasteroids.swf Move: Arrows | Стрелять: космос | Действия по перемотке: Backspace
Марсело Ассис
1

Была выпущена игра для XBox360, которая включала манипулирование временем. Это было посредственно, поэтому я не могу вспомнить название в настоящее время. Во всяком случае, в интервью с разработчиком они рассказали, как им удалось манипулировать временем:

Каждые X кадров (с более низкими значениями X, ведущими к более детальной манипуляции), вы берете «моментальный снимок» игрового мира в этот момент и связываете его со временем в игре.

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

Затем игровой мир выполняет итерации между моментальным снимком в текущий момент времени и кадрами X в будущем.

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

Джордаан Милонас
источник
+1 за точку о гранулярности снимков.
Омар Кохеджи
0

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

Предполагая некоторое взаимодействие с пользователем и какую-то физическую систему, которая определяет поведение вашей вселенной, когда нет ввода пользователя, все, что вам нужно записать, - это влияние взаимодействия с пользователем (например, изменения в векторах скорости / ускорения измерения n + 1) Так как ваша физика должна быть обратимой во времени.

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

biziclop
источник
Как я упоминал в другом комментарии, физика в видеоиграх, как правило, не обратима во времени, потому что при использовании чисел с плавающей запятой (x+v)-vне может быть равнымx
BlueRaja - Дэнни Пфлугхофт
0

Допустим, у объекта есть скорость, вращение, положение x и y. Это, с ускорением, основные состояния движения, ценности, как вы это называете. Вы можете сохранить данные двумя способами:
1. Сохранить вращение, координаты x и y
2. Сохранить вращение, скорость x и скорость y

Если у вас есть фиксированная скорость, вы также можете сохранить только вращение или сохранить только одну скорость для обеих осей.

Сохранение ротации необходимо в играх, если только у вашей сущности нет статической ротации, которой в большинстве случаев не является.

Тем не менее, использование списка объектов для нескольких значений необходимо. Если у вас есть хорошая система таймера, которая, например, вызывает методы обновления 20 раз в секунду и, следовательно, не зависит от fps, вы можете создать массив из 20 * 30 объектов для хранения необходимых вам значений движения в течение последних 30 секунд. , Использование простого массива не рекомендуется, так как вам придется перемещать каждый элемент на один индекс влево при каждом вызове обновления.

Исходя из этого, вы можете просмотреть список или что-то еще, чтобы вернуться. Если вы действительно хотите получить «реалистичный» эффект, используйте эту технику для всех движущихся объектов. Но это связано с игровым дизайном.

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

Marco
источник