Как кодировать Time Stop или Bullet Time в игре?

11

Я разрабатываю однопользовательский RPG-платформер в XNA 4.0. Я хотел бы добавить способность, которая заставляла бы время «останавливаться» или замедляться, и в котором только персонаж игрока двигался с первоначальной скоростью (аналогично заклинанию «Стоп времени» из серии «Врата Балдура»). Я не ищу точную реализацию, скорее некоторые общие идеи и шаблоны дизайна.

РЕДАКТИРОВАТЬ: Спасибо всем за большой вклад. Я придумал следующее решение

    public void Update(GameTime gameTime)
        {

            GameTime newGameTime = new GameTime(gameTime.TotalGameTime,
 new TimeSpan(gameTime.ElapsedGameTime.Ticks / DESIRED_TIME_MODIFIER));
            gameTime = newGameTime;

или что-то в этом роде. Таким образом, я могу установить другое время для компонента проигрывателя и другое для остальных. Это, конечно, не достаточно универсально, чтобы работать для игры, где искажение времени, как это, будет центральным элементом, но я надеюсь, что оно должно работать в этом случае. Мне немного не нравится тот факт, что он замусорил основной цикл обновления, но это, безусловно, самый простой способ реализовать его. Я предполагаю, что это в сущности то же самое, что предложил тесселоде, поэтому я собираюсь дать ему зеленую галочку :)

Дэвид Милер
источник

Ответы:

8

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

Например:

player.update(dt)
dt = dt * .5 --half speed
enemy.update(dt)

Это, конечно, работает, только если вы можете сказать, когда обновляете врага, а не что-то еще. Вы также можете просто дать всем значение скорости и сделать что-то вроде:

x = x + xspeed * dt * speed
tesselode
источник
Первая часть имеет смысл, вторая часть не ясна
AturSams
2
Просто дайте каждому объекту, который перемещает переменную скорости, которую вы можете изменить, и, когда у вас есть преобразование (например, x), умножьте величину на переменную скорости.
Тесселоде
Имеет смысл сейчас. :)
AturSams
Вторая идея звучит ... выкл. Простое масштабирование движения с помощью коэффициента «скорости» может работать для объектов, управляемых физикой, но ИИ сможет реагировать с нормальной скоростью, только замедляя / ослабляя его движение.
Что вы имеете в виду, что ИИ сможет реагировать с нормальной скоростью? Какой код будет иметь ИИ, к которому нельзя применить переменную скорости?
Тесселоде
3

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

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

Когда медленный эффект прекращается, часы все еще используются и увеличиваются на 100% от фактически прошедшего времени.

Это также может работать для заклинаний ускорения.

@ Сидар: я вижу два варианта,

  1. Внутренние часы на существо. Чтобы выяснить, готово ли существо к атаке снова: сохраните последний раз, когда использовалась каждая атака + время перезарядки и проверьте, прошли ли уже внутренние часы за это время.

  2. Один таймер на атаку: вы знаете, сколько времени занимает перезарядка атаки, и вы просто устанавливаете таймер и вычитаете время, которое прошло * (1-замедление%) каждый ход.

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

Это действительно зависит от предпочтений (это не сильно влияет на производительность).

AturSams
источник
Потребность во внутренних часах не нужна. Это просто сводится к множителю, который вы можете (каким-то образом) связать с вашим объектом, который либо увеличивает, либо уменьшает произведение вашего dt (дельта-времени). Вы можете управлять объектами группами или любым другим способом. Я думаю, что ваш путь может быть немного чрезмерным. Но эй, если это работает ... тогда это работает.
Сидар
@Sidar Если вы избегаете этого, вам, вероятно, понадобятся часы на атаку, чтобы рассчитать время перезарядки атаки, длительность заклинания и тому подобное. По крайней мере, таким образом вам нужно обновить только одни часы и просто сохранить время «последней активации» для сброса свойств.
AturSams
Однако его вопрос касается замедления окружающей среды, кроме игрока. Для меня это звучит как простейшая форма простого умножения dt на число меньше 1. Сохраняя это как для игрока.
Сидар
Ну, замедление окружения включает в себя замедление их скорости атаки, а также их других способностей (так как это ролевые игры), могут быть различные способности мобов, которые зависят от времени перезарядки. Лечение, баффы, дебаффы, заклинания и т. Д. Не говоря уже о времени активации.
AturSams
2

Вы можете начать с простого решения, такого как Тесселод или Мистер Бист. Но если вы начнете смешивать сложные вещи, например, время пули, когда заклинание замедления наложено, вы застрянете.

Я предлагаю вам реализовать иерархию часов :

.
├── Main clock
│   └── UI clock
│   └── 3D clock
│       ├── GFX clock
│       └── Gameplay clock
│           └── Slowdown spell clock 01
│           └── Slowdown spell clock 02

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

Лоран Кувиду
источник
Спасибо, это важное понимание. Тем не менее, я думаю, что я буду продолжать думать просто, поскольку в моем конкретном случае не имеет смысла, что несколько эффектов замедления будут происходить одновременно.
Дэвид Милер
1

Вам просто нужны две разные часы вместо одной, одна на время, относящееся к игровому процессу, и одна «истинная».

currentGameTime = 0;
gameSpeed = 1.0f;
[...]
currentApplicationTime = GetTime():
timeDelta = (currentApplicationTime - lastApplicationTime)*gameSpeed;
currentGameTime += timeDelta;
lastApplicationTime = currentApplicationTime;

Затем вы можете просто изменить gameSpeed, чтобы ускорить (> 1) или замедлить время (<1). Чтобы игрок двигался с разной скоростью, просто проверьте, замедлено ли время или нет.

API-Beast
источник