1 голос
 
1252 просмотра
6.09.2016 / 17:30  Death

Как ограничить FPS?

Столкнулся с такой проблемой как FPS.

Вот я делал WShooter, там у меня была проблемма с этим самым FPS, вот если я ставил паузу ври так: 1000/50, то на первых волнах было что нужно, но на следующих, где врагов больше 100, была уже тормажения приложения. А про то что когда было тысячи врагов на 500 волнах -- я уже молчу. Задал вопрос я на форму. Ответили мне простым способом как стабилизировать FPS. Получилось. Но всё 500 волны тормозили. Вот мне подсказали что можно сделать пропуск кадров. Вот тут мне вообще не приходит в голову, как это сделать. Помогите пожалуйста.
Изм. aNNiMON от 6.09.2016 / 17:32
Ответы
 
6 голосов
 
# 6.09.2016 / 18:37  aNNiMON
Пропуск кадров — обработка игровой логики при низком FPS без отрисовки.
У тебя есть отрисовка (напр. метод draw()) и обработка логики (напр. метод update()). В draw ты рисуешь врагов, в update изменяешь их координаты, обрабатываешь столкновения и т.д. Упрощенно, это выглядит так:
  1. while (игра_не_завершена) {
  2.     update();
  3.     draw();
  4. }
Один раз обновили, один раз отрисовали и так раз за разом.

При пропуске кадров, в момент падения FPS, мы вызываем update несколько раз, а отрисовываем один:
  1. while (игра_не_завершена) {
  2.     while (фпс_ниже_допустимого) {
  3.         update();
  4.     }
  5.     draw();
  6. }

Вышесказанное лишь для понимания сути, теперь к коду. В принципе, здесь всё легко, сложность может возникнуть лишь в определении низкого фпс.

  1. private static final int FPS = 30;
  2. private static final long DELAY = 1000 / FPS;
  3.  
  4. public void run() {
  5.     long startTime = System.currentTimeMillis();
  6.     long lag = 0;
  7.     while (gameRunning) {
  8.         long currentTime = System.currentTimeMillis();
  9.         long elapsed = currentTime - startTime;
  10.         startTime = currentTime;
  11.         lag += elapsed;
  12.         while (lag >= DELAY) {
  13.             update();
  14.             lag -= DELAY;
  15.         }
  16.         draw();
  17.     }
  18. }

В elapsed будет время, затраченное на обработку одного игрового такта (время выполнения update() и draw() вместе взятых).
Значение переменной lag при нормальных условиях всегда будет в пределах (0, DELAY).

Немного пояснений на примере

:ps: Разумеется, при таком подходе следует использовать двойную буферизацию, чтобы можно было рисовать из любого метода в BufferedImage. И вообще, с ней лучше.

Источники: Game Loop · Game Programming Patterns (перевод: Шаблоны игрового программирования. Игровой цикл: live13)
Изм. aNNiMON от 6.09.2016 / 18:47
 
1 голос
 
# 6.09.2016 / 17:36  vlavolk
Делать больше паузу между прорисовкой, это наиболее оптимальное решение.
Всего: 2

Реклама

Мы в соцсетях

tw tg yt gt