Сведения о вопросе

Mathprofi

00:16, 16th August, 2020

Теги

algorithm    

Как вы отделяете логику игры от дисплея?

Просмотров: 454   Ответов: 8

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



  Сведения об ответе

VERSUION

23:52, 3rd August, 2020

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

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

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

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

Это становится проблемой в следующем случае:

Регистрация вход: - Ввод является ключевым: 'W', что означает, что мы перемещаем персонажа игрока вперед на 10 единиц:

playerPosition += 10;

Теперь, поскольку вы делаете это каждый кадр, если вы работаете со скоростью 30 FPS, вы будете двигаться со скоростью 300 единиц в секунду.

Но если вы вместо этого работаете на 10 FPS, вы будете двигаться только 100 единиц в секунду. И поэтому ваша игровая логика не зависит от частоты кадров.

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

Во-первых, вам нужен таймер, который будет считать время, необходимое для визуализации каждого кадра. Это число в секундах (так что 0.001 секунд для завершения Тика) затем умножается на то, что вы хотите быть независимым от частоты кадров. Так что в данном случае:

При проведении 'W'

playerPosition += 10 * frameTimeDelta;

(Дельта-это модное слово для "изменения в чем-то")

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

Однако это будет падать, когда речь заходит о свойствах, где скорость изменения также меняется с течением времени, например, ускоряющийся автомобиль. Это можно решить с помощью более продвинутого интегратора, такого как "Verlet".

Многопоточный Подход

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

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

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

Фиксированный Временной Шаг Подхода

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

Ссылка здесь для полноты картины, но другой комментатор также ссылается на нее: Исправьте Свой Временной Шаг


  Сведения об ответе

crush

15:34, 4th August, 2020

У Коэна Виттерса есть очень подробная статья о различных настройках цикла игры.

Он покрывает:

  • FPS зависит от постоянной скорости игры
  • Скорость игры зависит от переменной FPS
  • Постоянная скорость игры с максимумом FPS
  • Постоянная скорость игры, не зависящая от переменной FPS

(Это заголовки, взятые из статьи, в порядке желательности.)


  Сведения об ответе

qwerty101

05:38, 26th August, 2020

Вы могли бы сделать свой игровой цикл похожим:

int lastTime = GetCurrentTime();
while(1) {
    // how long is it since we last updated?
    int currentTime = GetCurrentTime();
    int dt = currentTime - lastTime;
    lastTime = currentTime;

    // now do the game logic
    Update(dt);

    // and you can render
    Draw();
}

Тогда вам просто нужно написать свою функцию Update() , чтобы учесть разницу во времени; например , если у вас есть объект, движущийся с некоторой скоростью v, то обновляйте его положение на v * dt каждый кадр.


  Сведения об ответе

DO__IT

11:15, 24th August, 2020

В свое время об этом была отличная статья на flipcode. Я хотел бы откопать его и подарить вам.

http://www.flipcode.com/archives/Main_Loop_with_Fixed_Time_Steps.shtml

Это хорошо продуманная петля для запуска игры:

  1. Однопоточный
  2. На фиксированных игровых часах
  3. С графикой как можно быстрее с помощью интерполированных часов

Ну, по крайней мере, я так думаю. :- ) Жаль, что обсуждение, которое последовало после этой публикации, найти труднее. Возможно, машина обратного пути может помочь там.

time0 = getTickCount();
do
{
  time1 = getTickCount();
  frameTime = 0;
  int numLoops = 0;

  while ((time1 - time0)  TICK_TIME && numLoops < MAX_LOOPS)
  {
    GameTickRun();
    time0 += TICK_TIME;
    frameTime += TICK_TIME;
    numLoops++;
// Could this be a good idea? We're not doing it, anyway.
//    time1 = getTickCount();
  }
  IndependentTickRun(frameTime);

  // If playing solo and game logic takes way too long, discard pending
time.
  if (!bNetworkGame && (time1 - time0)  TICK_TIME)
    time0 = time1 - TICK_TIME;

  if (canRender)
  {
    // Account for numLoops overflow causing percent  1.
    float percentWithinTick = Min(1.f, float(time1 - time0)/TICK_TIME);
    GameDrawWithInterpolation(percentWithinTick);
  }
}
while (!bGameDone);


  Сведения об ответе

padenie

23:01, 3rd August, 2020

Это не распространяется на высшие программные абстракции, т. е. государственные машины и т. д.

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

Который может быть привязан к накопителю времени истекшего кадра (счетчику), BUT эти тайминги могут получить облажались, если частота кадров падает ниже вашего разрешения сценария состояния то есть, если ваша высшая логика нуждается в детализации 0.05 сек, и вы падаете ниже 20fps.

Детерминизм может быть сохранен, если логика игры выполняется на отдельном "thread" (на программном уровне, который я бы предпочел для этого, или на уровне OS) с фиксированным временным срезом, независимым от fps.

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


  Сведения об ответе

qwerty101

09:33, 8th August, 2020

Enginuity имеет несколько иной, но интересный подход: пул задач.


  Сведения об ответе

SKY

11:12, 6th August, 2020

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

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

Кроме того, извлечение GUI в отдельный поток кажется отличным подходом. Вы когда-нибудь видели всплывающее сообщение "Mission complete", когда юниты перемещаются в играх RTS? Вот о чем я говорю :)


  Сведения об ответе

P_S_S

21:06, 1st October, 2020

По моему опыту (не очень) ответы Джесси и Adam должны направить вас на правильный путь.

Если вам нужна дополнительная информация и понимание того, как это работает, я обнаружил, что примеры приложений для TrueVision 3D были очень полезны.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться