Игра работает на скорости 60 кадров в секунду, но после замедления она работает очень быстро в течение нескольких секунд

Я разрабатываю игру с плиткой. В большинстве случаев игра "уважает" ограничение 60 кадров в секунду, однако, когда я намеренно устанавливаю fps равным 10 кадрам в секунду в течение 5 секунд (с помощью отладки), чтобы проверить, что игровой рендеринг и логика игры работают раздельно, происходит то, что после того, как я возвращаюсь назад игра fps до 60 кадров в секунду, в течение нескольких секунд игра игнорирует "кепку" и работает со скоростью 10000 к / с, затем возвращается к пределу. Причина всего этого заключается в том, что я хочу, чтобы моя игра работала с переменной частотой кадров / с, но с постоянной логической скоростью на всех машинах, однако я не понимаю, почему моя игра в большинстве случаев соблюдает ограничение и никогда не поднимается выше 60 кадров / с, но когда происходит замедление или скачок задержки, игра проходит супер быстрее в течение 1-2 секунд, а затем возвращается в нормальное состояние. Независимо от того, работает ли пользователь на плохом компьютере, а игра работает на скорости 5 кадров в секунду, я хочу, чтобы игра никогда не превышала мою жесткую кепку.

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

new Thread(){
        public void run(){
            long hintPoint = System.currentTimeMillis();
            long nexttickG = System.currentTimeMillis();
            long nexttickL = System.currentTimeMillis();
            long nexttickV = System.currentTimeMillis();
            long ticktimeV = 1000;
            long LogicCap = 60;
            long ticktimeL = 1000/LogicCap;
            short frames = 60;

            while(isRunning){

                if(Main.servbot){
                    try {
                        Thread.sleep(15);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);

                short FramesCap = GLOBAL_FPS_CAP;
                long ticktimeG = 1000/FramesCap;

                if (System.currentTimeMillis()>nexttickG){
                    Render();
                    long elapsed = System.currentTimeMillis() - hintPoint;
                    frames=(short)((long)1000/(Math.max(elapsed,1)));
                    hintPoint = System.currentTimeMillis();
                    nexttickG+=ticktimeG;
                }

                if (System.currentTimeMillis()>nexttickL){
                    GameLoop();
                    nexttickL+=ticktimeL;
                }

                if (System.currentTimeMillis()>nexttickV){
                    GLOBAL_FPS_HINT = frames;

                    nexttickV+=ticktimeV;
                }

                Thread.yield();

            }

        }
    }.start();
}

2 ответа

Решение

Могут ли эти изменения помочь? (см. код ниже, ищите /* новый */).

Причина: вы устанавливаете точку останова в своем методе run ()? Какие вар (ы) вы изменяете

Сколько миллисекунд тикает в System.currentTimeMillis(), пока вы изменяете переменную (я) для изменения частоты кадров? Похоже, если вам потребуется 3 или 4 (возможно, 12) секунды, чтобы внести изменения и возобновить выполнение, ваши значения nextTickL и nextTickG будут значительно отставать от System.currentTimeMillis() и могут потребовать МНОГО добавлений += ticktimeG, чтобы наверстать упущенное на системные часы.

new Thread(){
    public void run(){
        long hintPoint = System.currentTimeMillis();
        long nexttickG = System.currentTimeMillis();
        long nexttickL = System.currentTimeMillis();
        long nexttickV = System.currentTimeMillis();
        long ticktimeV = 1000;
        long LogicCap = 60;
        long ticktimeL = 1000/LogicCap;
        short frames = 60;

        while(isRunning){

            if(Main.servbot){
                try {
                    Thread.sleep(15);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);

            short FramesCap = GLOBAL_FPS_CAP;
            long ticktimeG = 1000/FramesCap;

            if (System.currentTimeMillis()>nexttickG){
                Render();
                long elapsed = System.currentTimeMillis() - hintPoint;
                frames=(short)((long)1000/(Math.max(elapsed,1)));
                hintPoint = System.currentTimeMillis();
                nexttickG+=ticktimeG;
   /*new*/      if( nexttickG < System.currentTimeMillis() ) {
   /*new*/         // major clock skew somehow, reset.
   /*new*/         nexttickG = System.currentTimeMillis() + ticktimeG;
   /*new*/      }
            }

            if (System.currentTimeMillis()>nexttickL){
                GameLoop();
                nexttickL+=ticktimeL;
   /*new*/      if( nexttickL < System.currentTimeMillis() ) {
   /*new*/         // major clock skew somehow, reset.
   /*new*/         nexttickL = System.currentTimeMillis() + ticktimeL;
   /*new*/      }
            }

            if (System.currentTimeMillis()>nexttickV){
                GLOBAL_FPS_HINT = frames;

                nexttickV+=ticktimeV;
            }

            Thread.yield();

        }

    }
}.start();

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

И во-вторых, рассмотреть вопрос о реализации DELTA-TIME система, где FPS а также Game-World Time независимы друг от друга.

Delta-Time - это правильный шаблон петли для таких вещей, как анимация и игры (которые в основном являются программными, систематическими, а иногда и хаотичными анимациями game-world данные), потому что это самый простой шаблон, который избегает time-drift bugs из наиболее наивных / упрощенных animation-loop или же game-loop Реализации.

Вот пример того, как реализовать Delta-Time игровой цикл в Java.

Для полного объяснения проблемы с реализациями наивного цикла, и как Delta-Time решает проблему смещения времени (и, следовательно, почему она используется), взгляните на эту статью и эту статью, в которых подробно объясняются различия в игровых циклах.

Другие вопросы по тегам